class Shrine::Storage::S3
Constants
- COPY_OPTIONS
- MAX_MULTIPART_PARTS
- MIN_PART_SIZE
- MULTIPART_THRESHOLD
Attributes
Public Class Methods
# File lib/shrine/storage/s3.rb 71 def initialize(bucket:, client: nil, prefix: nil, upload_options: {}, multipart_threshold: {}, max_multipart_parts: nil, signer: nil, public: nil, copy_options: COPY_OPTIONS, **) 72 raise ArgumentError, "the :bucket option is nil" unless bucket 73 74 @client = client || Aws::S3::Client.new(**) 75 @transfer_manager = Aws::S3::TransferManager.new(client: @client) if defined?(Aws::S3::TransferManager) 76 @bucket = Aws::S3::Bucket.new(name: bucket, client: @client) 77 @prefix = prefix 78 @upload_options = upload_options 79 @copy_options = copy_options 80 @multipart_threshold = MULTIPART_THRESHOLD.merge(multipart_threshold) 81 @max_multipart_parts = max_multipart_parts || MAX_MULTIPART_PARTS 82 @signer = signer 83 @public = public 84 end
Initializes a storage for uploading to S3. All options are forwarded to Aws::S3::Client#initialize, except the following:
- :bucket
-
(Required). Name of the
S3bucket. - :client
-
By default an
Aws::S3::Clientinstance is created internally from additional options, but you can use this option to provide your own client. This can be anAws::S3::Clientor anAws::S3::Encryption::Clientobject. - :prefix
-
“Directory” inside the bucket to store files into.
- :upload_options
-
Additional options that will be used for uploading files, they will be passed to
Aws::S3::Object#put,Aws::S3::Object#copy_fromandAws::S3::Bucket#presigned_post. - :copy_options
-
Additional options that will be used for copying files, they will be passed to
Aws::S3::Object#copy_from. - :multipart_threshold
-
If the input file is larger than the specified size, a parallelized multipart will be used for the upload/copy. Defaults to
{upload: 15*1024*1024, copy: 100*1024*1024}(15MB for upload requests, 100MB for copy requests). - :max_multipart_parts
-
Limits the number of parts if parellized multipart upload/copy is used. Defaults to 10_000.
In addition to specifying the :bucket, you’ll also need to provide AWS credentials. The most common way is to provide them directly via :access_key_id, :secret_access_key, and :region options. But you can also use any other way of authentication specified in the AWS SDK documentation.
Public Instance Methods
Source
# File lib/shrine/storage/s3.rb 219 def clear!(&block) 220 objects_to_delete = bucket.objects(prefix: prefix) 221 objects_to_delete = objects_to_delete.lazy.select(&block) if block 222 223 delete_objects(objects_to_delete) 224 end
If block is given, deletes all objects from the storage for which the block evaluates to true. Otherwise deletes all objects from the storage.
s3.clear! # or s3.clear! { |object| object.last_modified < Time.now - 7*24*60*60 }
Source
# File lib/shrine/storage/s3.rb 199 def delete(id) 200 object(id).delete 201 end
Deletes the file from the storage.
# File lib/shrine/storage/s3.rb 206 def delete_prefixed(delete_prefix) 207 # We need to make sure to combine with storage prefix, and 208 # that it ends in '/' cause S3 can be squirrely about matching interior. 209 delete_prefix = delete_prefix.chomp("/") + "/" 210 bucket.objects(prefix: [*prefix, delete_prefix].join("/")).batch_delete! 211 end
Deletes objects at keys starting with the specified prefix.
s3.delete_prefixed(“somekey/derivatives/”)
Source
# File lib/shrine/storage/s3.rb 128 def exists?(id) 129 object(id).exists? 130 end
Returns true file exists on S3.
Source
# File lib/shrine/storage/s3.rb 227 def object(id) 228 bucket.object(object_key(id)) 229 end
Returns an Aws::S3::Object for the given id.
# File lib/shrine/storage/s3.rb 119 def open(id, rewindable: true, encoding: nil, **) 120 chunks, length = get(id, **) 121 122 Down::ChunkedIO.new(chunks: chunks, rewindable: rewindable, size: length, encoding: encoding) 123 rescue Aws::S3::Errors::NoSuchKey 124 raise Shrine::FileNotFound, "file #{id.inspect} not found on storage" 125 end
Returns a Down::ChunkedIO object that downloads S3 object content on-demand. By default, read content will be cached onto disk so that it can be rewinded, but if you don’t need that you can pass rewindable: false. A required character encoding can be passed in encoding; the default is Encoding::BINARY via Down::ChunkedIO.
Any additional options are forwarded to Aws::S3::Object#get.
# File lib/shrine/storage/s3.rb 189 def presign(id, method: :post, **presign_options) 190 options = {} 191 options[:acl] = "public-read" if public 192 193 options.merge!(@upload_options, presign_options) 194 195 send(:"presign_#{method}", id, options) 196 end
Returns URL, params, headers, and verb for direct uploads.
s3.presign("key") #=> # { # url: "https://my-bucket.s3.amazonaws.com/...", # fields: { ... }, # blank for PUT presigns # headers: { ... }, # blank for POST presigns # method: "post", # }
By default it calls Aws::S3::Object#presigned_post which generates data for a POST request, but you can also specify method: :put for PUT uploads which calls Aws::S3::Object#presigned_url.
s3.presign("key", method: :post) # for POST upload (default) s3.presign("key", method: :put) # for PUT upload
Any additional options are forwarded to the underlying AWS SDK method.
# File lib/shrine/storage/s3.rb 93 def upload(io, id, shrine_metadata: {}, **upload_options) 94 content_type, filename = shrine_metadata.values_at("mime_type", "filename") 95 96 options = {} 97 options[:content_type] = content_type if content_type 98 options[:content_disposition] = ContentDisposition.inline(filename) if filename 99 options[:acl] = "public-read" if public 100 101 options.merge!(@upload_options, upload_options) 102 103 if copyable?(io) 104 copy(io, id, **options) 105 else 106 put(io, id, **options) 107 end 108 end
If the file is an UploadedFile from S3, issues a COPY command, otherwise uploads the file. For files larger than :multipart_threshold a multipart upload/copy will be used for better performance and more resilient uploads.
It assigns the correct “Content-Type” taken from the MIME type, because by default S3 sets everything to “application/octet-stream”.
# File lib/shrine/storage/s3.rb 148 def url(id, public: self.public, host: nil, **) 149 if public || signer 150 url = object(id).public_url(**) 151 else 152 url = object(id).presigned_url(:get, **) 153 end 154 155 if host 156 uri = URI.parse(url) 157 uri.path = uri.path.match(/^\/#{bucket.name}/).post_match unless uri.host.include?(bucket.name) 158 url = URI.join(host, uri.request_uri[1..-1]).to_s 159 end 160 161 if signer 162 url = signer.call(url, **) 163 end 164 165 url 166 end
Returns the presigned URL to the file.
- :host
-
This option replaces the host part of the returned URL, and is typically useful for setting CDN hosts (e.g.
http://abc123.cloudfront.net) - :public
-
Returns the unsigned URL to the
S3object. This requires theS3object to be public.
All other options are forwarded to Aws::S3::Object#presigned_url or Aws::S3::Object#public_url.