shrine 3.0.0 → 3.2.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of shrine might be problematic. Click here for more details.

Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +87 -33
  3. data/LICENSE.txt +1 -1
  4. data/README.md +94 -4
  5. data/doc/advantages.md +35 -18
  6. data/doc/attacher.md +16 -17
  7. data/doc/carrierwave.md +75 -34
  8. data/doc/changing_derivatives.md +39 -39
  9. data/doc/design.md +134 -85
  10. data/doc/external/articles.md +56 -41
  11. data/doc/external/extensions.md +38 -34
  12. data/doc/getting_started.md +182 -112
  13. data/doc/metadata.md +79 -43
  14. data/doc/multiple_files.md +5 -3
  15. data/doc/paperclip.md +110 -42
  16. data/doc/plugins/activerecord.md +5 -5
  17. data/doc/plugins/add_metadata.md +92 -35
  18. data/doc/plugins/backgrounding.md +12 -2
  19. data/doc/plugins/column.md +36 -7
  20. data/doc/plugins/data_uri.md +2 -2
  21. data/doc/plugins/default_url.md +6 -3
  22. data/doc/plugins/derivation_endpoint.md +26 -28
  23. data/doc/plugins/derivatives.md +205 -169
  24. data/doc/plugins/determine_mime_type.md +2 -2
  25. data/doc/plugins/entity.md +3 -3
  26. data/doc/plugins/form_assign.md +5 -5
  27. data/doc/plugins/included.md +25 -5
  28. data/doc/plugins/infer_extension.md +2 -2
  29. data/doc/plugins/instrumentation.md +1 -1
  30. data/doc/plugins/metadata_attributes.md +21 -10
  31. data/doc/plugins/model.md +4 -4
  32. data/doc/plugins/persistence.md +1 -0
  33. data/doc/plugins/refresh_metadata.md +5 -4
  34. data/doc/plugins/remote_url.md +8 -3
  35. data/doc/plugins/remove_invalid.md +9 -1
  36. data/doc/plugins/sequel.md +4 -4
  37. data/doc/plugins/signature.md +11 -2
  38. data/doc/plugins/store_dimensions.md +2 -2
  39. data/doc/plugins/type_predicates.md +96 -0
  40. data/doc/plugins/upload_endpoint.md +7 -11
  41. data/doc/plugins/upload_options.md +1 -1
  42. data/doc/plugins/url_options.md +2 -2
  43. data/doc/plugins/validation.md +14 -4
  44. data/doc/plugins/validation_helpers.md +3 -3
  45. data/doc/plugins/versions.md +11 -11
  46. data/doc/processing.md +289 -125
  47. data/doc/refile.md +39 -18
  48. data/doc/release_notes/2.19.0.md +1 -1
  49. data/doc/release_notes/3.0.0.md +275 -258
  50. data/doc/release_notes/3.0.1.md +22 -0
  51. data/doc/release_notes/3.1.0.md +73 -0
  52. data/doc/release_notes/3.2.0.md +96 -0
  53. data/doc/release_notes/3.2.1.md +32 -0
  54. data/doc/release_notes/3.2.2.md +14 -0
  55. data/doc/securing_uploads.md +3 -3
  56. data/doc/storage/file_system.md +1 -1
  57. data/doc/storage/memory.md +19 -0
  58. data/doc/storage/s3.md +105 -86
  59. data/doc/testing.md +2 -2
  60. data/doc/upgrading_to_3.md +115 -33
  61. data/doc/validation.md +3 -2
  62. data/lib/shrine.rb +8 -8
  63. data/lib/shrine/attacher.rb +19 -14
  64. data/lib/shrine/attachment.rb +5 -5
  65. data/lib/shrine/plugins.rb +22 -0
  66. data/lib/shrine/plugins/add_metadata.rb +12 -3
  67. data/lib/shrine/plugins/default_storage.rb +6 -6
  68. data/lib/shrine/plugins/default_url.rb +1 -1
  69. data/lib/shrine/plugins/derivation_endpoint.rb +10 -6
  70. data/lib/shrine/plugins/derivatives.rb +19 -17
  71. data/lib/shrine/plugins/determine_mime_type.rb +3 -3
  72. data/lib/shrine/plugins/entity.rb +6 -6
  73. data/lib/shrine/plugins/metadata_attributes.rb +1 -1
  74. data/lib/shrine/plugins/model.rb +3 -3
  75. data/lib/shrine/plugins/presign_endpoint.rb +2 -2
  76. data/lib/shrine/plugins/pretty_location.rb +1 -1
  77. data/lib/shrine/plugins/processing.rb +1 -1
  78. data/lib/shrine/plugins/refresh_metadata.rb +2 -2
  79. data/lib/shrine/plugins/remote_url.rb +3 -3
  80. data/lib/shrine/plugins/remove_invalid.rb +10 -5
  81. data/lib/shrine/plugins/signature.rb +7 -6
  82. data/lib/shrine/plugins/store_dimensions.rb +18 -9
  83. data/lib/shrine/plugins/type_predicates.rb +113 -0
  84. data/lib/shrine/plugins/upload_endpoint.rb +3 -3
  85. data/lib/shrine/plugins/upload_options.rb +2 -2
  86. data/lib/shrine/plugins/url_options.rb +2 -2
  87. data/lib/shrine/plugins/validation.rb +9 -7
  88. data/lib/shrine/storage/linter.rb +4 -4
  89. data/lib/shrine/storage/s3.rb +62 -38
  90. data/lib/shrine/uploaded_file.rb +5 -1
  91. data/lib/shrine/version.rb +2 -2
  92. data/shrine.gemspec +6 -7
  93. metadata +23 -29
@@ -0,0 +1,22 @@
1
+ ---
2
+ title: Shrine 3.0.1
3
+ ---
4
+
5
+ ## Regressions
6
+
7
+ * Fixed `metadata_attributes` plugin raising an exception when the attachment
8
+ is removed (assigned to `nil`).
9
+
10
+ ## Improvements
11
+
12
+ * Simplified `UploadedFile#inspect` output:
13
+
14
+ ```rb
15
+ # before
16
+ uploaded_file.inspect
17
+ #=> #<Shrine::UploadedFile:0x00007fa4e4140d30 @id="cda84bbdab12b2bd41ea34590060a807", @storage_key=:memory, @metadata={"filename"=>nil, "size"=>0, "mime_type"=>nil}>
18
+
19
+ # after
20
+ uploaded_file.inspect
21
+ #=> #<Shrine::UploadedFile id="488b887dd792b4c82d3fc445140c5a38" storage=:memory metadata={"filename"=>nil, "size"=>0, "mime_type"=>nil}>
22
+ ```
@@ -0,0 +1,73 @@
1
+ ---
2
+ title: Shrine 3.1.0
3
+ ---
4
+
5
+ ## New features
6
+
7
+ * The `Attacher#create_derivatives` method now accepts a `:storage` option for
8
+ specifying the storage to which derivatives should be uploaded.
9
+
10
+ ```rb
11
+ # with attachment module
12
+ photo.image_derivatives!(storage: :other_store)
13
+
14
+ # with attacher
15
+ attacher.create_derivatives(storage: :other_store)
16
+ ```
17
+
18
+ * The `Shrine.calculate_signature` now accepts a `:rewind` boolean option for
19
+ choosing whether the IO object should be rewinded after reading. This is
20
+ useful if you want to calculate signature from non-rewindable IO objects,
21
+ such as `IO.pipe`, `Socket`, non-rewindable `Down::ChunkedIO` etc.
22
+
23
+ ```rb
24
+ Shrine.signature(io, rewind: false)
25
+ ```
26
+
27
+ ## Improvements
28
+
29
+ * The derivatives processor can now be registered with `Attacher.derivatives`,
30
+ which is just an alias for `Attacher.derivatives_processor`.
31
+
32
+ ```rb
33
+ class ImageUploader < Shrine
34
+ Attacher.derivatives_processor do |original|
35
+ # ...
36
+ end
37
+ end
38
+
39
+ # can now be written as
40
+
41
+ class ImageUploader < Shrine
42
+ Attacher.derivatives do |original|
43
+ # ...
44
+ end
45
+ end
46
+ ```
47
+
48
+ * The `Attacher#cached?` and `Attacher#stored?` methods now work correctly if
49
+ temporary/permanent storage identifiers were specified as strings.
50
+
51
+ * The `store_dimensions` plugin now properly propagates exceptions when loading
52
+ the `ruby-vips` gem in `:vips` analyzer.
53
+
54
+ * The `add_metadata` plugin now respects inheritance again when defining
55
+ metadata methods on the `Shrine::UploadedFile` class. In 2.19.0, the
56
+ `add_metadata` plugin was changed to define metadata methods on the internal
57
+ `FileMethods` plugin module, which is shared across all uploaders. This
58
+ change has now been reverted.
59
+
60
+ ## Backwards compatibility
61
+
62
+ * The `Attacher#cache_key` and `Attacher#store_key` methods now always return
63
+ symbol keys, even if the storage key that was specified was a string key.
64
+
65
+ ```rb
66
+ attacher = Shrine::Attacher.new(cache: "cache", store: "store")
67
+ attacher.cache_key #=> :cache (previously "cache")
68
+ attacher.store_key #=> :store (previously "store")
69
+ ```
70
+
71
+ * The `add_metadata` plugin now defines metadata methods directly on the
72
+ `UploadedFile` class, which means that if you happen to have been overriding
73
+ these metadata methods and calling `super`, this won't work anymore.
@@ -0,0 +1,96 @@
1
+ ---
2
+ title: Shrine 3.2.0
3
+ ---
4
+
5
+ ## New features
6
+
7
+ * The `type_predicates` plugin has been added, which adds convenient predicate
8
+ methods to `Shrine::UploadedFile` based on the MIME type.
9
+
10
+ ```rb
11
+ # Gemfile
12
+ gem "mini_mime" # default dependency of type_predicates
13
+ ```
14
+ ```rb
15
+ Shrine.plugin :type_predicates
16
+ ```
17
+
18
+ The plugin adds four predicate methods based on the general type of the file:
19
+
20
+ ```rb
21
+ file.image? # returns true for any "image/*" MIME type
22
+ file.video? # returns true for any "video/*" MIME type
23
+ file.audio? # returns true for any "audio/*" MIME type
24
+ file.text? # returns true for any "text/*" MIME type
25
+ ```
26
+
27
+ You can also check for specific MIME type using the extension name:
28
+
29
+ ```rb
30
+ file.type?(:jpg) # returns true if MIME type is "image/jpeg"
31
+ file.type?(:svg) # returns true if MIME type is "image/svg+xml"
32
+ file.type?(:mov) # returns true if MIME type is "video/quicktime"
33
+ file.type?(:ppt) # returns true if MIME type is "application/vnd.ms-powerpoint"
34
+ ...
35
+ ```
36
+
37
+ For convenience, you can create predicate methods for specific file types:
38
+
39
+ ```rb
40
+ Shrine.plugin :type_predicates, methods: %i[jpg svg mov ppt]
41
+ ```
42
+ ```rb
43
+ file.jpg? # returns true if MIME type is "image/jpeg"
44
+ file.svg? # returns true if MIME type is "image/svg+xml"
45
+ file.mov? # returns true if MIME type is "video/quicktime"
46
+ file.ppt? # returns true if MIME type is "application/vnd.ms-powerpoint"
47
+ ```
48
+
49
+ * The `#add_metadata` method has been added to the `add_metadata` plugin for
50
+ adding new metadata to an existing file/attachment.
51
+
52
+ ```rb
53
+ attacher.file.metadata #=> { ... }
54
+ attacher.add_metadata("foo" => "bar")
55
+ attacher.file.metadata #=> { ..., "foo" => "bar" }
56
+ ```
57
+
58
+ ## Other improvements
59
+
60
+ * The `remove_invalid` plugin now works correctly with `derivatives` plugin.
61
+
62
+ * The `remove_invalid` plugin is now also activated when `Attacher#validate`
63
+ is called manually.
64
+
65
+ * The current attached file data can now be assigned back to the attachment
66
+ attribute, and this operation will be a no-op.
67
+
68
+ ```rb
69
+ photo.image #=> #<Shrine::UploadedFile id="foo" storage=:store metadata={...}>
70
+ photo.image = { "id" => "foo", "storage" => "store", "metadata" => { ... } } # no-op
71
+ ```
72
+
73
+ This allows treating the attachment attribute as a persistent attribute,
74
+ where the current value can be assigned back on record updates.
75
+
76
+ * When promoting derivatives, the `:derivative` parameter value was being
77
+ passed to the uploader as an array. This has been fixed, and the value is now
78
+ the same as when uploading derivatives directly to permanent storage.
79
+
80
+ * The `derivatives` plugin now includes additional `:io` and `:attacher` values
81
+ in the instrumentation event payload.
82
+
83
+ ## Backwards compatibility
84
+
85
+ * The `validation` plugin now runs validations on `Attacher#attach` and
86
+ `Attacher#attach_cached`. If you were using `Attacher#change` directly and
87
+ expecting the validations to be run automatically, you will need to update
88
+ your code.
89
+
90
+ * If you were updating the cached file metadata via file data assignment, this
91
+ will no longer work.
92
+
93
+ ```rb
94
+ photo.image #=> #<Shrine::UploadedFile id="foo" storage=:cache metadata={...}>
95
+ photo.image = { "id" => "foo", "storage" => "cache", "metadata" => { ... } } # no-op
96
+ ```
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: Shrine 3.2.1
3
+ ---
4
+
5
+ ## Ruby 2.7 compatibility
6
+
7
+ * Shrine doesn't trigger [Ruby 2.7 warnings for separation of positional and
8
+ keyword arguments][kwargs] anymore.
9
+
10
+ * Down 5.1.0 has been released, which resolves warnings and a `FrozenError`
11
+ exception on Ruby 2.7. Shrine now requires at least this version of Down.
12
+
13
+ If you're using `Down::Http`, make sure you're using http.rb 4.3.0 or newer.
14
+
15
+ * ImageProcessing 1.10.3 gem has been released which resolves Ruby 2.7 warnings
16
+ as well. If you're using it for image processing, make sure to upgrade to
17
+ this version:
18
+
19
+ ```rb
20
+ gem "image_processing", ">= 1.10.3", "< 2"
21
+ ```
22
+
23
+ ## Rack 2.1.0 compatibility
24
+
25
+ * The `derivation_endpoint` plugin now uses `Rack::Files` on Rack 2.1.0 or
26
+ newer.
27
+
28
+ ## Other improvements
29
+
30
+ * The `S3#open` method now handles empty S3 objects.
31
+
32
+ [kwargs]: https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/
@@ -0,0 +1,14 @@
1
+ ---
2
+ title: Shrine 3.2.2
3
+ ---
4
+
5
+ ## Bug fixes
6
+
7
+ * aws-sdk-core 3.104.0 introduced a backwards incompatible changes that caused
8
+ `Shrine::Storage::S3#open` to start raising an exception.
9
+
10
+ ```
11
+ NoMethodError: undefined method `bytesize' for #<Array:0x000000000a721be0>
12
+ ```
13
+
14
+ This has now been fixed.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: securing-uploads
3
- title: Securing uploads
3
+ title: Securing Uploads
4
4
  ---
5
5
 
6
6
  Shrine does a lot to make your file uploads secure, but there are still a lot
@@ -63,7 +63,7 @@ in the `:max_size` option to reject files that are larger than the specified
63
63
  limit:
64
64
 
65
65
  ```rb
66
- plugin :upload_endpoint, max_size: 100*1024*1024 # 20 MB
66
+ plugin :upload_endpoint, max_size: 100*1024*1024 # 100 MB
67
67
  ```
68
68
 
69
69
  If you're doing direct uploads to Amazon S3 using the `presign_endpoint`
@@ -151,7 +151,7 @@ processing:
151
151
  ```rb
152
152
  class ImageUploader < Shrine
153
153
  # ...
154
- Attacher.derivatives_processor do |original|
154
+ Attacher.derivatives do |original|
155
155
  width, height = Shrine.dimensions(original)
156
156
 
157
157
  fail ImageBombError if width > 5000 || height > 5000
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  id: file-system
3
- title: Shrine::Storage::FileSystem
3
+ title: File System
4
4
  ---
5
5
 
6
6
  The FileSystem storage handles uploads to the filesystem, and it is most
@@ -0,0 +1,19 @@
1
+ ---
2
+ title: Memory
3
+ ---
4
+
5
+ The Memory storage stores uploaded files in memory, which is suitable for
6
+ testing.
7
+
8
+ ```rb
9
+ Shrine.storages[:store] = Shrine::Storage::Memory.new
10
+ ```
11
+
12
+ By default, each storage instance uses a new Hash object for storing files,
13
+ but you can pass your own:
14
+
15
+ ```rb
16
+ my_store = Hash.new
17
+
18
+ Shrine.storages[:store] = Shrine::Storage::Memory.new(my_store)
19
+ ```
@@ -1,31 +1,41 @@
1
1
  ---
2
- title: Shrine::Storage::S3
2
+ title: AWS S3
3
3
  ---
4
4
 
5
- The S3 storage handles uploads to Amazon S3 service, using the [aws-sdk-s3]
5
+ The S3 storage handles uploads to [AWS S3] service (or any s3-compatible
6
+ service such as [DigitalOcean Spaces] or [MinIO]). It requires the [aws-sdk-s3]
6
7
  gem:
7
8
 
8
9
  ```rb
10
+ # Gemfile
9
11
  gem "aws-sdk-s3", "~> 1.14"
10
12
  ```
11
13
 
12
- It can be initialized by providing the bucket name and credentials:
14
+ ## Initialization
15
+
16
+ The storage is initialized by providing your bucket name, region and
17
+ credentials:
13
18
 
14
19
  ```rb
15
20
  require "shrine/storage/s3"
16
21
 
17
22
  s3 = Shrine::Storage::S3.new(
18
23
  bucket: "my-app", # required
24
+ region: "eu-west-1", # required
19
25
  access_key_id: "abc",
20
26
  secret_access_key: "xyz",
21
- region: "eu-west-1",
22
27
  )
23
28
  ```
24
29
 
25
- The core features of this storage require the following AWS permissions:
26
- `s3:ListBucket`, `s3:PutObject`, `s3:GetObject`, and `s3:DeleteObject`. If you
27
- have additional upload options configured such as setting object ACLs, then
28
- additional permissions may be required.
30
+ > The storage requires the following AWS S3 permissions:
31
+ >
32
+ > * `s3:ListBucket` for the bucket resource
33
+ > * `s3:GetObject`, `s3:PutObject`, `s3:PutObjectAcl`, `s3:DeleteObject`,
34
+ > `s3:ListMultipartUploadParts` and `s3:AbortMultipartUpload` for the object
35
+ > resources
36
+
37
+ > The `:access_key_id` and `:secret_access_key` options is just one form of
38
+ > authentication, see the [AWS SDK docs][credentials] for more options.
29
39
 
30
40
  The storage exposes the underlying Aws objects:
31
41
 
@@ -45,14 +55,29 @@ s3.object("key") #=> #<Aws::S3::Object>
45
55
 
46
56
  By default, uploaded S3 objects will have private visibility, meaning they can
47
57
  only be accessed via signed expiring URLs generated using your private S3
48
- credentials. If you would like to generate public URLs, you can tell S3 storage
49
- to make uploads public:
58
+ credentials.
50
59
 
51
60
  ```rb
52
- s3 = Shrine::Storage::S3.new(public: true, **s3_options)
61
+ s3 = Shrine::Storage::S3.new(**s3_options)
62
+ s3.upload(io, "key") # uploads with default "private" ACL
63
+ s3.url("key") # https://my-bucket.s3.amazonaws.com/key?X-Amz-Expires=900&X-Amz-Signature=b22d37c37d...
64
+ ```
53
65
 
66
+ If you would like to generate public URLs, you can tell S3 storage to make
67
+ uploads public:
68
+
69
+ ```rb
70
+ s3 = Shrine::Storage::S3.new(public: true, **s3_options)
54
71
  s3.upload(io, "key") # uploads with "public-read" ACL
55
- s3.url("key") # returns public (unsigned) object URL
72
+ s3.url("key") # https://my-bucket.s3.amazonaws.com/key
73
+ ```
74
+
75
+ If you want to make only *some* uploads public, you can conditionally apply the
76
+ `:acl` upload option and `:public` URL option:
77
+
78
+ ```rb
79
+ Shrine.plugin :upload_options, store: -> (io, **) { { acl: "public-read" } }
80
+ Shrine.plugin :url_options, store: -> (io, **) { { public: true } }
56
81
  ```
57
82
 
58
83
  ## Prefix
@@ -80,13 +105,11 @@ You can also generate upload options per upload with the `upload_options`
80
105
  plugin
81
106
 
82
107
  ```rb
83
- class MyUploader < Shrine
84
- plugin :upload_options, store: -> (io, derivative: nil, **) do
85
- if derivative == :thumb
86
- { acl: "public-read" }
87
- else
88
- { acl: "private" }
89
- end
108
+ Shrine.plugin :upload_options, store: -> (io, derivative: nil, **) do
109
+ if derivative == :thumb
110
+ { acl: "public-read" }
111
+ else
112
+ { acl: "private" }
90
113
  end
91
114
  end
92
115
  ```
@@ -97,23 +120,9 @@ or when using the uploader directly
97
120
  uploader.upload(file, upload_options: { acl: "private" })
98
121
  ```
99
122
 
100
- Note that, unlike the `:upload_options` storage option, upload options given on
101
- the uploader level won't be forwarded for generating presigns, since presigns
102
- are generated using the storage directly.
103
-
104
- ## URL options
105
-
106
- Other than [`:host`](#url-host) and [`:public`](#public-uploads) URL options,
107
- all additional options are forwarded to [`Aws::S3::Object#presigned_url`].
108
-
109
- ```rb
110
- s3.url(
111
- expires_in: 15,
112
- response_content_disposition: ContentDisposition.attachment("my-filename"),
113
- response_content_type: "foo/bar",
114
- # ...
115
- )
116
- ```
123
+ > Unlike the `:upload_options` storage option, upload options given on
124
+ the uploader level won't be forwarded for generating presigns, since presigns
125
+ are generated using the storage directly.
117
126
 
118
127
  ## URL Host
119
128
 
@@ -133,12 +142,14 @@ s3.url("image.jpg", host: "https://your-s3-host.com/prefix/") # needs to end wit
133
142
  ```
134
143
 
135
144
  To have the `:host` option passed automatically for every URL, use the
136
- `url_options` plugin.
145
+ `url_options` plugin:
137
146
 
138
147
  ```rb
139
148
  plugin :url_options, store: { host: "http://abc123.cloudfront.net" }
140
149
  ```
141
150
 
151
+ ### Signer
152
+
142
153
  If you would like to [serve private content via CloudFront], you need to sign
143
154
  the object URLs with a special signer, such as [`Aws::CloudFront::UrlSigner`]
144
155
  provided by the `aws-sdk-cloudfront` gem. The S3 storage initializer accepts a
@@ -157,13 +168,27 @@ Shrine::Storage::S3.new(signer: signer.method(:signed_url))
157
168
  Shrine::Storage::S3.new(signer: -> (url, **options) { signer.signed_url(url, **options) })
158
169
  ```
159
170
 
171
+ ## URL options
172
+
173
+ Other than `:host` and `:public` URL options, all additional `S3#url` options
174
+ are forwarded to [`Aws::S3::Object#presigned_url`].
175
+
176
+ ```rb
177
+ s3.url(
178
+ expires_in: 15,
179
+ response_content_disposition: ContentDisposition.attachment("my-filename"),
180
+ response_content_type: "foo/bar",
181
+ # ...
182
+ )
183
+ ```
184
+
160
185
  ## Presigns
161
186
 
162
- The `#presign` method can be used for generating paramters for direct uploads
163
- to Amazon S3:
187
+ The `S3#presign` method can be used for generating parameters for direct upload
188
+ to S3:
164
189
 
165
190
  ```rb
166
- s3.presign("/path/to/file") #=>
191
+ s3.presign("key") #=>
167
192
  # {
168
193
  # url: "https://my-bucket.s3.amazonaws.com/...",
169
194
  # fields: { ... }, # blank for PUT presigns
@@ -172,11 +197,25 @@ s3.presign("/path/to/file") #=>
172
197
  # }
173
198
  ```
174
199
 
175
- Additional presign options can be given in three places:
200
+ By default, parameters for a POST upload is generated, but you can also
201
+ generate PUT upload parameters:
176
202
 
177
- * in `Storage::S3#presign` by forwarding options
178
- * in `:upload_options` option on this storage
179
- * in `presign_endpoint` plugin through `:presign_options`
203
+ ```rb
204
+ s3.presign("key", method: :put)
205
+ ```
206
+
207
+ Any additional options are forwarded to [`Aws::S3::Object#presigned_post`]
208
+ (for POST uploads) and [`Aws::S3::Object#presigned_url`] (for PUT uploads).
209
+
210
+ ```rb
211
+ s3.presign("key", method: :put, content_disposition: "attachment; filename=my-file.txt") #=>
212
+ # {
213
+ # url: "https://my-bucket.s3.amazonaws.com/...",
214
+ # fields: {},
215
+ # headers: { "Content-Disposition" => "attachment; filename=my-file.txt" },
216
+ # method :put,
217
+ # }
218
+ ```
180
219
 
181
220
  ## Large files
182
221
 
@@ -184,33 +223,24 @@ The aws-sdk-s3 gem has the ability to automatically use multipart upload/copy
184
223
  for larger files, splitting the file into multiple chunks and uploading/copying
185
224
  them in parallel.
186
225
 
187
- By default any files that are uploaded will use the multipart upload if they're
188
- larger than 15MB, and any files that are copied will use the multipart copy if
189
- they're larger than 150MB, but you can change the thresholds via
190
- `:multipart_threshold`.
226
+ By default, multipart upload will be used for files larger than 15MB, and
227
+ multipart copy for files larger than 100MB, but you can change the thresholds
228
+ via `:multipart_threshold`:
191
229
 
192
230
  ```rb
193
- thresholds = { upload: 30*1024*1024, copy: 200*1024*1024 }
194
- Shrine::Storage::S3.new(multipart_threshold: thresholds, **s3_options)
195
- ```
196
-
197
- If you want to change how many threads aws-sdk-s3 will use for multipart
198
- upload/copy, you can use the `upload_options` plugin to specify
199
- `:thread_count`.
200
-
201
- ```rb
202
- plugin :upload_options, store: -> (io, context) do
203
- { thread_count: 5 }
204
- end
231
+ Shrine::Storage::S3.new(
232
+ multipart_threshold: { upload: 30*1024*1024, copy: 200*1024*1024 },
233
+ **s3_options,
234
+ )
205
235
  ```
206
236
 
207
237
  ## Encryption
208
238
 
209
- The easiest way to use server-side encryption for uploaded S3 objects is to
239
+ The easiest way to use **server-side** encryption for uploaded S3 objects is to
210
240
  configure default encryption for your S3 bucket. Alternatively, you can pass
211
241
  server-side encryption parameters to the API calls.
212
242
 
213
- The `#upload` method accepts `:sse_*` options:
243
+ The `S3#upload` method accepts `:sse_*` options:
214
244
 
215
245
  ```rb
216
246
  s3.upload(io, "key", sse_customer_algorithm: "AES256",
@@ -219,7 +249,7 @@ s3.upload(io, "key", sse_customer_algorithm: "AES256",
219
249
  ssekms_key_id: "key_id")
220
250
  ```
221
251
 
222
- The `#presign` method accepts `:server_side_encryption_*` options for POST
252
+ The `S3#presign` method accepts `:server_side_encryption_*` options for POST
223
253
  presigns, and the same `:sse_*` options as above for PUT presigns.
224
254
 
225
255
  ```rb
@@ -232,25 +262,14 @@ When downloading encrypted S3 objects, the same server-side encryption
232
262
  parameters need to be passed in.
233
263
 
234
264
  ```rb
235
- s3.download("key", sse_customer_algorithm: "AES256",
236
- sse_customer_key: "secret_key",
237
- sse_customer_key_md5: "secret_key_md5")
238
-
239
265
  s3.open("key", sse_customer_algorithm: "AES256",
240
266
  sse_customer_key: "secret_key",
241
267
  sse_customer_key_md5: "secret_key_md5")
242
268
  ```
243
269
 
244
- If you want to use client-side encryption instead, you can instantiate the
245
- storage with an `Aws::S3::Encryption::Client` instance.
246
-
247
- ```rb
248
- client = Aws::S3::Encryption::Client.new(
249
- kms_key_id: "alias/my-key"
250
- )
251
-
252
- Shrine::Storage::S3(client: client, bucket: "my-bucket")
253
- ```
270
+ If you want to use **client-side** encryption instead, note that it's still a
271
+ work in progress, see issue [#348] for some discussion and
272
+ [workarounds][client-side encryption workaround].
254
273
 
255
274
  ## Accelerate endpoint
256
275
 
@@ -283,20 +302,20 @@ Alternatively you can periodically call the `#clear!` method:
283
302
  s3.clear! { |object| object.last_modified < Time.now - 7*24*60*60 }
284
303
  ```
285
304
 
286
- ## Request Rate and Performance Guidelines
287
-
288
- Amazon S3 automatically scales to high request rates. For example, your
289
- application can achieve at least 3,500 PUT/POST/DELETE and 5,500 GET requests
290
- per second per prefix in a bucket (a prefix is a top-level "directory" in the
291
- bucket). If your app needs to support higher request rates to S3 than that, you
292
- can scale exponentially by using more prefixes.
293
-
305
+ [AWS S3]: https://aws.amazon.com/s3/
306
+ [MinIO]: https://min.io/
307
+ [DigitalOcean Spaces]: https://www.digitalocean.com/products/spaces/
308
+ [aws-sdk-s3]: https://rubygems.org/gems/aws-sdk-s3
294
309
  [uploading]: http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#put-instance_method
295
310
  [copying]: http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#copy_from-instance_method
296
311
  [presigning]: http://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#presigned_post-instance_method
297
312
  [`Aws::S3::Object#presigned_url`]: https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#presigned_url-instance_method
298
- [aws-sdk-s3]: https://github.com/aws/aws-sdk-ruby/tree/master/gems/aws-sdk-s3
299
313
  [Transfer Acceleration]: http://docs.aws.amazon.com/AmazonS3/latest/dev/transfer-acceleration.html
300
314
  [object lifecycle]: http://docs.aws.amazon.com/AmazonS3/latest/UG/lifecycle-configuration-bucket-no-versioning.html
301
315
  [serve private content via CloudFront]: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html
302
316
  [`Aws::CloudFront::UrlSigner`]: https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/CloudFront/UrlSigner.html
317
+ [credentials]: https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/setup-config.html
318
+ [`Aws::S3::Object#presigned_post`]: https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#presigned_post-instance_method
319
+ [`Aws::S3::Object#presigned_url`]: https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Object.html#presigned_url-instance_method
320
+ [#348]: https://github.com/shrinerb/shrine/issues/348
321
+ [client-side encryption workaround]: https://github.com/shrinerb/shrine/issues/348#issuecomment-486445382