diff options
author | David Heinemeier Hansson <david@loudthinking.com> | 2017-07-03 15:35:46 +0200 |
---|---|---|
committer | David Heinemeier Hansson <david@loudthinking.com> | 2017-07-03 15:35:46 +0200 |
commit | 951b2ee57d7463f14775d3c1b0fa220daf5844d4 (patch) | |
tree | 13e5795c270ac09b98e559a61a7e271a46aba62f | |
parent | 59d3e03b81d09c70fc1249514c1848e701757513 (diff) | |
parent | 29d65979f0db385d9872ba56221526638ad3db96 (diff) | |
download | rails-951b2ee57d7463f14775d3c1b0fa220daf5844d4.tar.gz rails-951b2ee57d7463f14775d3c1b0fa220daf5844d4.tar.bz2 rails-951b2ee57d7463f14775d3c1b0fa220daf5844d4.zip |
Merge branch 'master' of github.com:basecamp/activefile
-rw-r--r-- | Gemfile | 4 | ||||
-rw-r--r-- | Gemfile.lock | 10 | ||||
-rw-r--r-- | lib/active_file/blob.rb | 5 | ||||
-rw-r--r-- | lib/active_file/sites/s3_site.rb | 69 |
4 files changed, 82 insertions, 6 deletions
@@ -4,4 +4,6 @@ gemspec gem 'rake' gem 'byebug' -gem 'sqlite3'
\ No newline at end of file + +gem 'sqlite3' +gem 'aws-sdk'
\ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index d7dc3e105d..0438cb67fb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -24,11 +24,20 @@ GEM minitest (~> 5.1) tzinfo (~> 1.1) arel (8.0.0) + aws-sdk (2.10.7) + aws-sdk-resources (= 2.10.7) + aws-sdk-core (2.10.7) + aws-sigv4 (~> 1.0) + jmespath (~> 1.0) + aws-sdk-resources (2.10.7) + aws-sdk-core (= 2.10.7) + aws-sigv4 (1.0.0) byebug (9.0.6) concurrent-ruby (1.0.5) globalid (0.4.0) activesupport (>= 4.2.0) i18n (0.8.4) + jmespath (1.3.1) minitest (5.10.2) rake (12.0.0) sqlite3 (1.3.13) @@ -41,6 +50,7 @@ PLATFORMS DEPENDENCIES activefile! + aws-sdk bundler (~> 1.15) byebug rake diff --git a/lib/active_file/blob.rb b/lib/active_file/blob.rb index b5d149e1fa..98bbcd057f 100644 --- a/lib/active_file/blob.rb +++ b/lib/active_file/blob.rb @@ -7,14 +7,9 @@ class ActiveFile::Blob < ActiveRecord::Base has_secure_token :key store :metadata, coder: JSON - class_attribute :verifier, default: -> { Rails.application.message_verifier('ActiveFile') } class_attribute :site class << self - def find_verified(signed_id) - find(verifier.verify(signed_id)) - end - def build_after_upload(data:, filename:, content_type: nil, metadata: nil) new.tap do |blob| blob.filename = name 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 |