From cc2c5f428ae0606fe37050772c248bafafd187f0 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sun, 2 Jul 2017 16:47:28 +0200 Subject: Start on S3 site --- lib/active_file/sites/s3_site.rb | 69 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 lib/active_file/sites/s3_site.rb (limited to 'lib/active_file/sites/s3_site.rb') diff --git a/lib/active_file/sites/s3_site.rb b/lib/active_file/sites/s3_site.rb new file mode 100644 index 0000000000..46c409405a --- /dev/null +++ b/lib/active_file/sites/s3_site.rb @@ -0,0 +1,69 @@ +require "aws-sdk" + +class ActiveFile::Sites::S3Site < ActiveFile::Site + attr_reader :client, :bucket + + def initialize(access_key_id:, secret_access_key:, region:, bucket:) + @client = Aws::S3::Resource.new(access_key_id: access_key_id, secret_access_key: secret_access_key, region: region) + @bucket = @client.bucket(bucket) + end + + def upload(key, data) + object_for(key).put(body: data) + end + + def download(key) + if block_given? + stream(key, &block) + else + object_for(key).read + end + end + + def delete(key) + object_for(key).delete + end + + def exists?(key) + object_for(key).exists? + end + + + def byte_size(key) + object_for(key).head[:size] + end + + def checksum(key) + head = object_for(key).head + + # If the etag has no dashes, it's the MD5 + if !head.etag.include?("-") + head.etag.gsub('"', '') + # Check for md5 in metadata if it was uploaded via multipart + elsif md5sum = head.meta["md5sum"] + md5sum + # Otherwise, we don't have a digest yet for this key + else + nil + end + end + + + private + def object_for(key) + bucket.object(key) + end + + # Reads the object for the given key in chunks, yielding each to the block. + def stream(key, options = {}, &block) + object = object_for(key) + + chunk_size = 5242880 # 5 megabytes + offset = 0 + + while offset < object.content_length + yield object.read(options.merge(:range => "bytes=#{offset}-#{offset + chunk_size - 1}")) + offset += chunk_size + end + end +end -- cgit v1.2.3