aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@loudthinking.com>2017-07-06 15:38:01 +0200
committerDavid Heinemeier Hansson <david@loudthinking.com>2017-07-06 15:38:01 +0200
commit152c4b07248d4aed4b734721bd634e546a89ef19 (patch)
treeda0003f340d2294a14d15cc2bc7773c935600298
parent6de714a0ea755caafe5758e232582573ac9966a4 (diff)
downloadrails-152c4b07248d4aed4b734721bd634e546a89ef19.tar.gz
rails-152c4b07248d4aed4b734721bd634e546a89ef19.tar.bz2
rails-152c4b07248d4aed4b734721bd634e546a89ef19.zip
Compute checksum and byte_size client side
Then we can add integrity checks on uploads to prevent errors in transport.
-rw-r--r--lib/active_storage/blob.rb18
-rw-r--r--lib/active_storage/service/disk_service.rb10
-rw-r--r--lib/active_storage/service/gcs_service.rb14
-rw-r--r--lib/active_storage/service/s3_service.rb10
-rw-r--r--test/service/shared_service_tests.rb8
5 files changed, 15 insertions, 45 deletions
diff --git a/lib/active_storage/blob.rb b/lib/active_storage/blob.rb
index 4ce344e2a1..b10dc2c771 100644
--- a/lib/active_storage/blob.rb
+++ b/lib/active_storage/blob.rb
@@ -42,10 +42,10 @@ class ActiveStorage::Blob < ActiveRecord::Base
def upload(io)
- service.upload(key, io)
+ self.checksum = compute_checksum_in_chunks(io)
+ self.byte_size = io.size
- self.checksum = service.checksum(key)
- self.byte_size = service.byte_size(key)
+ service.upload(key, io)
end
def download
@@ -65,4 +65,16 @@ class ActiveStorage::Blob < ActiveRecord::Base
def purge_later
ActiveStorage::PurgeJob.perform_later(self)
end
+
+
+ private
+ def compute_checksum_in_chunks(io)
+ Digest::MD5.new.tap do |checksum|
+ while chunk = io.read(5.megabytes)
+ checksum << chunk
+ end
+
+ io.rewind
+ end.base64digest
+ end
end
diff --git a/lib/active_storage/service/disk_service.rb b/lib/active_storage/service/disk_service.rb
index 7981226a1e..98e0f5eb7f 100644
--- a/lib/active_storage/service/disk_service.rb
+++ b/lib/active_storage/service/disk_service.rb
@@ -36,7 +36,6 @@ class ActiveStorage::Service::DiskService < ActiveStorage::Service
File.exist? path_for(key)
end
-
def url(key, expires_in:, disposition:, filename:)
verified_key_with_expiration = ActiveStorage::VerifiedKeyWithExpiration.encode(key, expires_in: expires_in)
@@ -47,15 +46,6 @@ class ActiveStorage::Service::DiskService < ActiveStorage::Service
end
end
- def byte_size(key)
- File.size path_for(key)
- end
-
- def checksum(key)
- Digest::MD5.file(path_for(key)).hexdigest
- end
-
-
private
def path_for(key)
File.join root, folder_for(key), key
diff --git a/lib/active_storage/service/gcs_service.rb b/lib/active_storage/service/gcs_service.rb
index c2f520d996..c725afb35c 100644
--- a/lib/active_storage/service/gcs_service.rb
+++ b/lib/active_storage/service/gcs_service.rb
@@ -28,27 +28,13 @@ class ActiveStorage::Service::GCSService < ActiveStorage::Service
file_for(key).present?
end
-
def url(key, expires_in:, disposition:, filename:)
file_for(key).signed_url(expires: expires_in) + "&" +
{ "response-content-disposition" => "#{disposition}; filename=\"#{filename}\"" }.to_query
end
- def byte_size(key)
- file_for(key).size
- end
-
- def checksum(key)
- convert_to_hex base64: file_for(key).md5
- end
-
-
private
def file_for(key)
bucket.file(key)
end
-
- def convert_to_hex(base64:)
- base64.unpack("m0").first.unpack("H*").first
- end
end
diff --git a/lib/active_storage/service/s3_service.rb b/lib/active_storage/service/s3_service.rb
index c94f5ddc63..cb08893c0e 100644
--- a/lib/active_storage/service/s3_service.rb
+++ b/lib/active_storage/service/s3_service.rb
@@ -28,21 +28,11 @@ class ActiveStorage::Service::S3Service < ActiveStorage::Service
object_for(key).exists?
end
-
def url(key, expires_in:, disposition:, filename:)
object_for(key).presigned_url :get, expires_in: expires_in,
response_content_disposition: "#{disposition}; filename=\"#{filename}\""
end
- def byte_size(key)
- object_for(key).size
- end
-
- def checksum(key)
- object_for(key).etag.remove(/"/)
- end
-
-
private
def object_for(key)
bucket.object(key)
diff --git a/test/service/shared_service_tests.rb b/test/service/shared_service_tests.rb
index 16672ab49b..3676272e27 100644
--- a/test/service/shared_service_tests.rb
+++ b/test/service/shared_service_tests.rb
@@ -51,13 +51,5 @@ module ActiveStorage::Service::SharedServiceTests
@service.delete FIXTURE_KEY
assert_not @service.exist?(FIXTURE_KEY)
end
-
- test "sizing" do
- assert_equal FIXTURE_FILE.size, @service.byte_size(FIXTURE_KEY)
- end
-
- test "checksumming" do
- assert_equal Digest::MD5.hexdigest(FIXTURE_FILE.read), @service.checksum(FIXTURE_KEY)
- end
end
end