aboutsummaryrefslogtreecommitdiffstats
path: root/activestorage/app
diff options
context:
space:
mode:
authorGeorge Claghorn <george.claghorn@gmail.com>2018-01-15 13:06:17 -0500
committerGitHub <noreply@github.com>2018-01-15 13:06:17 -0500
commitc2ba530c43244b5b60fd629f61cd8b44c43ecda9 (patch)
tree76c572f419a8e30b4ba2d2ae22570844ba28361e /activestorage/app
parentd8e7d6b03c50f4f01c333461c46666d8210e2c17 (diff)
downloadrails-c2ba530c43244b5b60fd629f61cd8b44c43ecda9.tar.gz
rails-c2ba530c43244b5b60fd629f61cd8b44c43ecda9.tar.bz2
rails-c2ba530c43244b5b60fd629f61cd8b44c43ecda9.zip
Extract content types from blob data
Diffstat (limited to 'activestorage/app')
-rw-r--r--activestorage/app/models/active_storage/attachment.rb6
-rw-r--r--activestorage/app/models/active_storage/blob.rb14
-rw-r--r--activestorage/app/models/active_storage/blob/identifiable.rb11
-rw-r--r--activestorage/app/models/active_storage/identification.rb38
4 files changed, 64 insertions, 5 deletions
diff --git a/activestorage/app/models/active_storage/attachment.rb b/activestorage/app/models/active_storage/attachment.rb
index 9f61a5dbf3..19f48c57d6 100644
--- a/activestorage/app/models/active_storage/attachment.rb
+++ b/activestorage/app/models/active_storage/attachment.rb
@@ -14,7 +14,7 @@ class ActiveStorage::Attachment < ActiveRecord::Base
delegate_missing_to :blob
- after_create_commit :analyze_blob_later
+ after_create_commit :identify_blob, :analyze_blob_later
# Synchronously purges the blob (deletes it from the configured service) and destroys the attachment.
def purge
@@ -29,6 +29,10 @@ class ActiveStorage::Attachment < ActiveRecord::Base
end
private
+ def identify_blob
+ blob.identify
+ end
+
def analyze_blob_later
blob.analyze_later unless blob.analyzed?
end
diff --git a/activestorage/app/models/active_storage/blob.rb b/activestorage/app/models/active_storage/blob.rb
index 2ac09d3062..7067c58259 100644
--- a/activestorage/app/models/active_storage/blob.rb
+++ b/activestorage/app/models/active_storage/blob.rb
@@ -14,12 +14,12 @@
# update a blob's metadata on a subsequent pass, but you should not update the key or change the uploaded file.
# If you need to create a derivative or otherwise change the blob, simply create a new blob and purge the old one.
class ActiveStorage::Blob < ActiveRecord::Base
- include Analyzable, Representable
+ include Analyzable, Identifiable, Representable
self.table_name = "active_storage_blobs"
has_secure_token :key
- store :metadata, accessors: [ :analyzed ], coder: JSON
+ store :metadata, accessors: [ :analyzed, :identified ], coder: JSON
class_attribute :service
@@ -136,8 +136,10 @@ class ActiveStorage::Blob < ActiveRecord::Base
# Normally, you do not have to call this method directly at all. Use the factory class methods of +build_after_upload+
# and +create_after_upload!+.
def upload(io)
- self.checksum = compute_checksum_in_chunks(io)
- self.byte_size = io.size
+ self.checksum = compute_checksum_in_chunks(io)
+ self.content_type = extract_content_type(io)
+ self.byte_size = io.size
+ self.identified = true
service.upload(key, io, checksum: checksum)
end
@@ -182,6 +184,10 @@ class ActiveStorage::Blob < ActiveRecord::Base
end.base64digest
end
+ def extract_content_type(io)
+ Marcel::MimeType.for io, name: filename.to_s, declared_type: content_type
+ end
+
def forcibly_serve_as_binary?
ActiveStorage.content_types_to_serve_as_binary.include?(content_type)
end
diff --git a/activestorage/app/models/active_storage/blob/identifiable.rb b/activestorage/app/models/active_storage/blob/identifiable.rb
new file mode 100644
index 0000000000..40ca84ac70
--- /dev/null
+++ b/activestorage/app/models/active_storage/blob/identifiable.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module ActiveStorage::Blob::Identifiable
+ def identify
+ ActiveStorage::Identification.new(self).apply
+ end
+
+ def identified?
+ identified
+ end
+end
diff --git a/activestorage/app/models/active_storage/identification.rb b/activestorage/app/models/active_storage/identification.rb
new file mode 100644
index 0000000000..4f295257ae
--- /dev/null
+++ b/activestorage/app/models/active_storage/identification.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+class ActiveStorage::Identification
+ attr_reader :blob
+
+ def initialize(blob)
+ @blob = blob
+ end
+
+ def apply
+ blob.update!(content_type: content_type, identified: true) unless blob.identified?
+ end
+
+ private
+ def content_type
+ Marcel::MimeType.for(identifiable_chunk, name: filename, declared_type: declared_content_type)
+ end
+
+
+ def identifiable_chunk
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |client|
+ client.get(uri, "Range" => "0-4096").body
+ end
+ end
+
+ def uri
+ @uri ||= URI.parse(blob.service_url)
+ end
+
+
+ def filename
+ blob.filename.to_s
+ end
+
+ def declared_content_type
+ blob.content_type
+ end
+end