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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +87 -33
- data/LICENSE.txt +1 -1
- data/README.md +94 -4
- data/doc/advantages.md +35 -18
- data/doc/attacher.md +16 -17
- data/doc/carrierwave.md +75 -34
- data/doc/changing_derivatives.md +39 -39
- data/doc/design.md +134 -85
- data/doc/external/articles.md +56 -41
- data/doc/external/extensions.md +38 -34
- data/doc/getting_started.md +182 -112
- data/doc/metadata.md +79 -43
- data/doc/multiple_files.md +5 -3
- data/doc/paperclip.md +110 -42
- data/doc/plugins/activerecord.md +5 -5
- data/doc/plugins/add_metadata.md +92 -35
- data/doc/plugins/backgrounding.md +12 -2
- data/doc/plugins/column.md +36 -7
- data/doc/plugins/data_uri.md +2 -2
- data/doc/plugins/default_url.md +6 -3
- data/doc/plugins/derivation_endpoint.md +26 -28
- data/doc/plugins/derivatives.md +205 -169
- data/doc/plugins/determine_mime_type.md +2 -2
- data/doc/plugins/entity.md +3 -3
- data/doc/plugins/form_assign.md +5 -5
- data/doc/plugins/included.md +25 -5
- data/doc/plugins/infer_extension.md +2 -2
- data/doc/plugins/instrumentation.md +1 -1
- data/doc/plugins/metadata_attributes.md +21 -10
- data/doc/plugins/model.md +4 -4
- data/doc/plugins/persistence.md +1 -0
- data/doc/plugins/refresh_metadata.md +5 -4
- data/doc/plugins/remote_url.md +8 -3
- data/doc/plugins/remove_invalid.md +9 -1
- data/doc/plugins/sequel.md +4 -4
- data/doc/plugins/signature.md +11 -2
- data/doc/plugins/store_dimensions.md +2 -2
- data/doc/plugins/type_predicates.md +96 -0
- data/doc/plugins/upload_endpoint.md +7 -11
- data/doc/plugins/upload_options.md +1 -1
- data/doc/plugins/url_options.md +2 -2
- data/doc/plugins/validation.md +14 -4
- data/doc/plugins/validation_helpers.md +3 -3
- data/doc/plugins/versions.md +11 -11
- data/doc/processing.md +289 -125
- data/doc/refile.md +39 -18
- data/doc/release_notes/2.19.0.md +1 -1
- data/doc/release_notes/3.0.0.md +275 -258
- data/doc/release_notes/3.0.1.md +22 -0
- data/doc/release_notes/3.1.0.md +73 -0
- data/doc/release_notes/3.2.0.md +96 -0
- data/doc/release_notes/3.2.1.md +32 -0
- data/doc/release_notes/3.2.2.md +14 -0
- data/doc/securing_uploads.md +3 -3
- data/doc/storage/file_system.md +1 -1
- data/doc/storage/memory.md +19 -0
- data/doc/storage/s3.md +105 -86
- data/doc/testing.md +2 -2
- data/doc/upgrading_to_3.md +115 -33
- data/doc/validation.md +3 -2
- data/lib/shrine.rb +8 -8
- data/lib/shrine/attacher.rb +19 -14
- data/lib/shrine/attachment.rb +5 -5
- data/lib/shrine/plugins.rb +22 -0
- data/lib/shrine/plugins/add_metadata.rb +12 -3
- data/lib/shrine/plugins/default_storage.rb +6 -6
- data/lib/shrine/plugins/default_url.rb +1 -1
- data/lib/shrine/plugins/derivation_endpoint.rb +10 -6
- data/lib/shrine/plugins/derivatives.rb +19 -17
- data/lib/shrine/plugins/determine_mime_type.rb +3 -3
- data/lib/shrine/plugins/entity.rb +6 -6
- data/lib/shrine/plugins/metadata_attributes.rb +1 -1
- data/lib/shrine/plugins/model.rb +3 -3
- data/lib/shrine/plugins/presign_endpoint.rb +2 -2
- data/lib/shrine/plugins/pretty_location.rb +1 -1
- data/lib/shrine/plugins/processing.rb +1 -1
- data/lib/shrine/plugins/refresh_metadata.rb +2 -2
- data/lib/shrine/plugins/remote_url.rb +3 -3
- data/lib/shrine/plugins/remove_invalid.rb +10 -5
- data/lib/shrine/plugins/signature.rb +7 -6
- data/lib/shrine/plugins/store_dimensions.rb +18 -9
- data/lib/shrine/plugins/type_predicates.rb +113 -0
- data/lib/shrine/plugins/upload_endpoint.rb +3 -3
- data/lib/shrine/plugins/upload_options.rb +2 -2
- data/lib/shrine/plugins/url_options.rb +2 -2
- data/lib/shrine/plugins/validation.rb +9 -7
- data/lib/shrine/storage/linter.rb +4 -4
- data/lib/shrine/storage/s3.rb +62 -38
- data/lib/shrine/uploaded_file.rb +5 -1
- data/lib/shrine/version.rb +2 -2
- data/shrine.gemspec +6 -7
- 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.
|
data/doc/securing_uploads.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
---
|
2
2
|
id: securing-uploads
|
3
|
-
title: Securing
|
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 #
|
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.
|
154
|
+
Attacher.derivatives do |original|
|
155
155
|
width, height = Shrine.dimensions(original)
|
156
156
|
|
157
157
|
fail ImageBombError if width > 5000 || height > 5000
|
data/doc/storage/file_system.md
CHANGED
@@ -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
|
+
```
|
data/doc/storage/s3.md
CHANGED
@@ -1,31 +1,41 @@
|
|
1
1
|
---
|
2
|
-
title:
|
2
|
+
title: AWS S3
|
3
3
|
---
|
4
4
|
|
5
|
-
The S3 storage handles uploads to
|
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
|
-
|
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
|
26
|
-
|
27
|
-
|
28
|
-
|
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.
|
49
|
-
to make uploads public:
|
58
|
+
credentials.
|
50
59
|
|
51
60
|
```rb
|
52
|
-
s3 = Shrine::Storage::S3.new(
|
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") #
|
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
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
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
|
-
|
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
|
163
|
-
to
|
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("
|
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
|
-
|
200
|
+
By default, parameters for a POST upload is generated, but you can also
|
201
|
+
generate PUT upload parameters:
|
176
202
|
|
177
|
-
|
178
|
-
|
179
|
-
|
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
|
188
|
-
|
189
|
-
|
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
|
-
|
194
|
-
|
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
|
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
|
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,
|
245
|
-
|
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
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
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
|