shrine 2.13.0 → 2.14.0
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 +72 -0
- data/README.md +20 -16
- data/doc/creating_storages.md +0 -21
- data/doc/design.md +1 -0
- data/doc/direct_s3.md +26 -15
- data/doc/metadata.md +67 -22
- data/doc/multiple_files.md +3 -3
- data/doc/processing.md +1 -1
- data/doc/retrieving_uploads.md +184 -0
- data/lib/shrine.rb +268 -900
- data/lib/shrine/attacher.rb +271 -0
- data/lib/shrine/attachment.rb +97 -0
- data/lib/shrine/plugins.rb +29 -0
- data/lib/shrine/plugins/_urlsafe_serialization.rb +182 -0
- data/lib/shrine/plugins/activerecord.rb +16 -14
- data/lib/shrine/plugins/add_metadata.rb +58 -24
- data/lib/shrine/plugins/backgrounding.rb +6 -1
- data/lib/shrine/plugins/cached_attachment_data.rb +9 -9
- data/lib/shrine/plugins/copy.rb +12 -8
- data/lib/shrine/plugins/data_uri.rb +23 -20
- data/lib/shrine/plugins/default_url_options.rb +5 -4
- data/lib/shrine/plugins/determine_mime_type.rb +24 -23
- data/lib/shrine/plugins/download_endpoint.rb +61 -73
- data/lib/shrine/plugins/migration_helpers.rb +17 -17
- data/lib/shrine/plugins/module_include.rb +9 -8
- data/lib/shrine/plugins/presign_endpoint.rb +13 -7
- data/lib/shrine/plugins/processing.rb +1 -1
- data/lib/shrine/plugins/rack_response.rb +128 -36
- data/lib/shrine/plugins/refresh_metadata.rb +20 -5
- data/lib/shrine/plugins/remote_url.rb +8 -8
- data/lib/shrine/plugins/remove_attachment.rb +9 -9
- data/lib/shrine/plugins/sequel.rb +21 -18
- data/lib/shrine/plugins/tempfile.rb +68 -0
- data/lib/shrine/plugins/upload_endpoint.rb +3 -2
- data/lib/shrine/plugins/upload_options.rb +7 -6
- data/lib/shrine/plugins/validation_helpers.rb +2 -1
- data/lib/shrine/storage/file_system.rb +20 -17
- data/lib/shrine/storage/linter.rb +0 -7
- data/lib/shrine/storage/s3.rb +159 -50
- data/lib/shrine/uploaded_file.rb +258 -0
- data/lib/shrine/version.rb +1 -1
- data/shrine.gemspec +7 -19
- metadata +41 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 705f49f8a110b3b50eb00c0fdf17da95dce2fa7782aaadfe20808af178a46405
|
4
|
+
data.tar.gz: 41789005e3146dc56a327d7d0c4fe6de12153cb8135789a9a3cf56212fdd1d13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f9ed520831fb14e199ef8ee9bddeaac47f7cf4151c5eb66ad68620c8c45db6c01d4fc4d62c6ff87a9bed2a771d48c97cc234ba903f1c3bf4005e79bcfa52d33
|
7
|
+
data.tar.gz: e70bbbd5f5731778112c4ce700df42b08b207368b5898625dbff8123faae40e383e7429b134d3850c485bfc5cab1e142a6c123f6e1a4adc6bb3d430484377a82
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,73 @@
|
|
1
|
+
## 2.14.0 (2018-12-27)
|
2
|
+
|
3
|
+
* Add `tempfile` plugin for easier reusing of the same uploaded file copy on disk (@janko-m)
|
4
|
+
|
5
|
+
* Don't re-open the uploaded file if it's already open in `refresh_metadata` plugin (@janko-m)
|
6
|
+
|
7
|
+
* Drop support for MRI 2.1 and 2.2 (@janko-m)
|
8
|
+
|
9
|
+
* Fix `backgrounding` not working when default storage was changed with `Attachment.new` (@janko-m)
|
10
|
+
|
11
|
+
* Don't clear existing metadata definitions when loading `add_metadata` plugin (@janko-m)
|
12
|
+
|
13
|
+
* Don't clear existing processing blocks when loading `processing` plugin (@janko-m)
|
14
|
+
|
15
|
+
* Deprecate automatic escaping of `:content_disposition` in `Shrine::Storage::S3` (@janko-m)
|
16
|
+
|
17
|
+
* Use `content_disposition` gem in `Shrine::Storage::S3` and `rack_response` plugin (@janko-m)
|
18
|
+
|
19
|
+
* Make `FileSystem#clear!` work correctly when the storage directory is a symlink (@janko-m)
|
20
|
+
|
21
|
+
* Don't abort promotion in `backgrounding` plugin when original metadata was updated (@janko-m)
|
22
|
+
|
23
|
+
* Don't mutate the `UploadedFile` data hash in `refresh_metadata` plugin (@janko-m)
|
24
|
+
|
25
|
+
* Deprecate `Storage::S3#download` (@janko-m)
|
26
|
+
|
27
|
+
* Stop using `Storage#download` in `UploadedFile#download` for peformance (@janko-m)
|
28
|
+
|
29
|
+
* Remove `#download` from the Shrine storage specification (@janko-m)
|
30
|
+
|
31
|
+
* Keep `context` argument in `#extract_metadata` optional after loading `add_metadata` plugin (@janko-m)
|
32
|
+
|
33
|
+
* Include metadata key with `nil` value when `nil` is returned in `add_metadata` block (@janko-m)
|
34
|
+
|
35
|
+
* Strip query params in upload location when re-uploading from `shrine-url` storage (@jrochkind)
|
36
|
+
|
37
|
+
* Inline Base plugin into core classes, extract them to separate files (@printercu)
|
38
|
+
|
39
|
+
* Make `rack_response` plugin work with `Rack::Sendfile` for `FileSystem` storage (@janko-m)
|
40
|
+
|
41
|
+
* Add `:filename` and `:type` options to `rack_response` plugin (@janko-m)
|
42
|
+
|
43
|
+
* Add `:host` option to `UploadedFile#download_url` in `download_endpoint` plugin (@janko-m)
|
44
|
+
|
45
|
+
* Add support for client-side encryption to S3 storage (@janko-m)
|
46
|
+
|
47
|
+
* Don't look up the attachment class in each new model instance (@printercu)
|
48
|
+
|
49
|
+
* Allow `Attacher#cached?` and `Attacher#stored?` to take an `UploadedFile` object (@jrochkind)
|
50
|
+
|
51
|
+
* Allow assigning a filename to the `DataFile` object in `Shrine.data_uri` (@janko-m)
|
52
|
+
|
53
|
+
* Don't strip media type parameters for the `DataFile` object in `data_uri` plugin (@janko-m)
|
54
|
+
|
55
|
+
* Add `:content_type` analyzer to `Shrine.mime_type_analyzers` in `determine_mime_type` plugin (@janko-m)
|
56
|
+
|
57
|
+
* Rename `:default` analyzer to `:content_type` in `determine_mime_type` plugin (@janko-m)
|
58
|
+
|
59
|
+
* Don't display a warning when `determine_mime_type` plugin is loaded with `:default` analyzer (@janko-m)
|
60
|
+
|
61
|
+
* Exclude media type parameters when copying `IO#content_type` into `mime_type` metadata (@janko-m)
|
62
|
+
|
63
|
+
* Remove superfluous `#head_object` S3 API call in `S3#download` (@janko-m)
|
64
|
+
|
65
|
+
* Make `S3#download` and `S3#open` work with server side encryption options (@janko-m)
|
66
|
+
|
67
|
+
* Make previously extracted metadata available under `:metadata` in `add_metadata` plugin (@jrochkind)
|
68
|
+
|
69
|
+
* Use a guard raise cause for `bucket` argument in S3 for an appropriate error message (@ardecvz)
|
70
|
+
|
1
71
|
## 2.13.0 (2018-11-04)
|
2
72
|
|
3
73
|
* Specify UTF-8 charset in `Content-Type` response header in `presign_endpoint` plugin (@janko-m)
|
@@ -6,6 +76,8 @@
|
|
6
76
|
|
7
77
|
* Force UTF-8 encoding on filenames coming from Rack's multipart request params in `rack_file` plugin (@janko-m)
|
8
78
|
|
79
|
+
* Raise `Shrine::Error` if `file` command returns error in stdout in `determine_mime_type` plugin (@janko-m)
|
80
|
+
|
9
81
|
* Allow `:host` in `S3#url` to specify a host URL with an additional path prefix (@janko-m)
|
10
82
|
|
11
83
|
* Revert adding bucket name to URL path in `S3#url` when `:host` is used with `:force_path_style` (@janko-m)
|
data/README.md
CHANGED
@@ -226,12 +226,12 @@ plugin is loaded.
|
|
226
226
|
Here are some examples of IO objects that can be uploaded:
|
227
227
|
|
228
228
|
```rb
|
229
|
-
uploader.upload File.open("/path/to/file",
|
230
|
-
uploader.upload StringIO.new("file content")
|
231
|
-
uploader.upload ActionDispatch::Http::UploadedFile.new
|
232
|
-
uploader.upload Shrine.rack_file({ tempfile:
|
233
|
-
uploader.upload Rack::Test::UploadedFile.new
|
234
|
-
uploader.upload Down.open("https://example.org/file")
|
229
|
+
uploader.upload File.open("/path/to/file", binmode: true) # upload from disk
|
230
|
+
uploader.upload StringIO.new("file content") # upload from memory
|
231
|
+
uploader.upload ActionDispatch::Http::UploadedFile.new # upload from Rails controller
|
232
|
+
uploader.upload Shrine.rack_file({ tempfile: tempfile }) # upload from Rack controller
|
233
|
+
uploader.upload Rack::Test::UploadedFile.new # upload from rack-test
|
234
|
+
uploader.upload Down.open("https://example.org/file") # upload from internet
|
235
235
|
```
|
236
236
|
|
237
237
|
`Shrine::UploadedFile`, the object returned after upload, is itself an IO-like
|
@@ -285,12 +285,8 @@ uploaded_file.rewind # rewinds the IO
|
|
285
285
|
uploaded_file.close # closes the IO
|
286
286
|
```
|
287
287
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
```rb
|
292
|
-
uploaded_file.open(&:read) #=> "..." (binary content of the uploaded file)
|
293
|
-
```
|
288
|
+
For more details on these `Shrine::UploadedFile` methods, see the [Retrieving
|
289
|
+
Uploads] guide.
|
294
290
|
|
295
291
|
## Attachment
|
296
292
|
|
@@ -465,6 +461,13 @@ uploaded_file.mime_type #=> "video/mp4"
|
|
465
461
|
uploaded_file.size #=> 345993
|
466
462
|
```
|
467
463
|
|
464
|
+
By default these values are determined from the following attributes on the IO
|
465
|
+
object:
|
466
|
+
|
467
|
+
* `filename` – `io.original_filename` or `io.path`
|
468
|
+
* `mime_type` – `io.content_type`
|
469
|
+
* `size` – `io.size`
|
470
|
+
|
468
471
|
### MIME type
|
469
472
|
|
470
473
|
By default `mime_type` will be inherited from `#content_type` attribute of the
|
@@ -765,7 +768,7 @@ Shrine.plugin :presign_endpoint
|
|
765
768
|
```
|
766
769
|
```rb
|
767
770
|
# config.ru (Rack)
|
768
|
-
map "/
|
771
|
+
map "/s3/params" do
|
769
772
|
run Shrine.presign_endpoint(:cache)
|
770
773
|
end
|
771
774
|
|
@@ -773,11 +776,11 @@ end
|
|
773
776
|
|
774
777
|
# config/routes.rb (Rails)
|
775
778
|
Rails.application.routes.draw do
|
776
|
-
mount Shrine.presign_endpoint(:cache) => "/
|
779
|
+
mount Shrine.presign_endpoint(:cache) => "/s3/params"
|
777
780
|
end
|
778
781
|
```
|
779
782
|
|
780
|
-
The above will add a `GET /
|
783
|
+
The above will add a `GET /s3/params` route to your app. You can now hook Uppy's
|
781
784
|
[AWS S3][uppy aws s3] plugin to this endpoint and have it upload directly to
|
782
785
|
S3. See [this walkthrough][direct S3 uploads walkthrough] that shows adding
|
783
786
|
direct S3 uploads from scratch, as well as the [Direct Uploads to S3][direct S3
|
@@ -789,7 +792,7 @@ If you wanted to implement this enpdoint yourself, this is how it could roughly
|
|
789
792
|
look like for S3 storage in Sinatra:
|
790
793
|
|
791
794
|
```rb
|
792
|
-
get "/
|
795
|
+
get "/s3/params" do
|
793
796
|
storage = Shrine.storages[:cache]
|
794
797
|
location = SecureRandom.hex + File.extname(params["filename"].to_s)
|
795
798
|
|
@@ -990,6 +993,7 @@ The gem is available as open source under the terms of the [MIT License].
|
|
990
993
|
[external storages]: https://shrinerb.com/#external
|
991
994
|
[creating storage]: https://shrinerb.com/rdoc/files/doc/creating_storages_md.html
|
992
995
|
[creating plugin]: https://shrinerb.com/rdoc/files/doc/creating_plugins_md.html
|
996
|
+
[Retrieving Uploads]: https://shrinerb.com/rdoc/files/doc/retrieving_uploads_md.html
|
993
997
|
[Using Attacher]: https://shrinerb.com/rdoc/files/doc/attacher_md.html
|
994
998
|
[plugins]: https://shrinerb.com/#plugins
|
995
999
|
[`file`]: http://linux.die.net/man/1/file
|
data/doc/creating_storages.md
CHANGED
@@ -122,27 +122,6 @@ The storage can support additional options to customize how the file will be
|
|
122
122
|
opened, `Shrine::UploadedFile#open` and `Shrine::UploadedFile#download` will
|
123
123
|
forward any given options to `#open`.
|
124
124
|
|
125
|
-
## Download
|
126
|
-
|
127
|
-
`Shrine::UploadedFile#download` by default uses the `#open` storage method to
|
128
|
-
stream file content to a Tempfile. However, if you would like to use your own
|
129
|
-
custom way of downloading to a file, you can define `#download` on the storage
|
130
|
-
and `Shrine::UploadedFile#download` will automatically call that instead.
|
131
|
-
|
132
|
-
```rb
|
133
|
-
class MyStorage
|
134
|
-
# ...
|
135
|
-
def download(id, **options)
|
136
|
-
# download the uploaded file to a Tempfile
|
137
|
-
end
|
138
|
-
# ...
|
139
|
-
end
|
140
|
-
```
|
141
|
-
|
142
|
-
The storage can support additional options to customize how the file will be
|
143
|
-
downloaded, `Shrine::UploadedFile#download` will forward any given options to
|
144
|
-
`#download`.
|
145
|
-
|
146
125
|
## Url
|
147
126
|
|
148
127
|
The `#url` storage method is called by `Shrine::UploadedFile#url`, it accepts a
|
data/doc/design.md
CHANGED
data/doc/direct_s3.md
CHANGED
@@ -96,25 +96,26 @@ S3. It's recommended to use [Uppy] for client side uploads.
|
|
96
96
|
The `presign_endpoint` plugin provides a Rack application that generates these
|
97
97
|
upload parameters, which we can just mount in our application. We'll make our
|
98
98
|
presign endpoint also use the additional `type` and `filename` query parameters
|
99
|
-
to set `Content-Type`
|
100
|
-
as limit the upload size to 10 MB (see
|
101
|
-
list of available options).
|
99
|
+
to set `Content-Type` header, `Content-Disposition` header (using the
|
100
|
+
[content_disposition] gem), as well as limit the upload size to 10 MB (see
|
101
|
+
[`Shrine::Storage::S3#presign`] for the list of available options).
|
102
102
|
|
103
103
|
```rb
|
104
104
|
Shrine.plugin :presign_endpoint, presign_options: -> (request) {
|
105
|
+
# Uppy will send the "filename" and "type" query parameters
|
105
106
|
filename = request.params["filename"]
|
106
107
|
type = request.params["type"]
|
107
108
|
|
108
109
|
{
|
109
|
-
content_disposition:
|
110
|
-
content_type: type,
|
111
|
-
content_length_range: 0..(10*1024*1024),
|
110
|
+
content_disposition: ContentDisposition.inline(filename), # set download filename
|
111
|
+
content_type: type, # set content type (required if using DigitalOcean Spaces)
|
112
|
+
content_length_range: 0..(10*1024*1024), # limit upload size to 10 MB
|
112
113
|
}
|
113
114
|
}
|
114
115
|
```
|
115
116
|
```rb
|
116
117
|
# config.ru (Rack)
|
117
|
-
map "/
|
118
|
+
map "/s3/params" do
|
118
119
|
run Shrine.presign_endpoint(:cache)
|
119
120
|
end
|
120
121
|
|
@@ -122,17 +123,17 @@ end
|
|
122
123
|
|
123
124
|
# config/routes.rb (Rails)
|
124
125
|
Rails.application.routes.draw do
|
125
|
-
mount Shrine.presign_endpoint(:cache) => "/
|
126
|
+
mount Shrine.presign_endpoint(:cache) => "/s3/params"
|
126
127
|
end
|
127
128
|
```
|
128
129
|
|
129
|
-
The above will create a `GET /
|
130
|
+
The above will create a `GET /s3/params` route, which internally calls
|
130
131
|
[`Shrine::Storage::S3#presign`] to return the HTTP verb (POST) and the S3 URL
|
131
132
|
to which the file should be uploaded, along with the required POST parameters
|
132
133
|
and request headers.
|
133
134
|
|
134
135
|
```rb
|
135
|
-
# GET /
|
136
|
+
# GET /s3/params
|
136
137
|
{
|
137
138
|
"method": "post",
|
138
139
|
"url": "https://my-bucket.s3-eu-west-1.amazonaws.com",
|
@@ -148,11 +149,11 @@ and request headers.
|
|
148
149
|
}
|
149
150
|
```
|
150
151
|
|
151
|
-
Uppy's [AWS S3][uppy aws s3] plugin would then make a request to this endpoint
|
152
|
-
parameters to upload the file directly to S3. Once the file has
|
153
|
-
you can generate a JSON representation of the uploaded file on
|
154
|
-
and write it to the hidden attachment field (or send it
|
155
|
-
request).
|
152
|
+
Uppy's [AWS S3][uppy aws s3] plugin would then make a request to this endpoint
|
153
|
+
and use these parameters to upload the file directly to S3. Once the file has
|
154
|
+
been uploaded, you can generate a JSON representation of the uploaded file on
|
155
|
+
the client side, and write it to the hidden attachment field (or send it
|
156
|
+
directly in an AJAX request).
|
156
157
|
|
157
158
|
```rb
|
158
159
|
{
|
@@ -176,6 +177,13 @@ upload walkthrough] for adding dynamic direct S3 uploads from scratch, as well
|
|
176
177
|
as the [Roda][roda demo] / [Rails][rails demo] demo app for a complete example
|
177
178
|
of multiple direct S3 uploads.
|
178
179
|
|
180
|
+
Also, if you're dealing with larger files, you may want to make the uploads
|
181
|
+
resumable by using the [Aws S3 Multipart][uppy aws s3 multipart] Uppy plugin
|
182
|
+
instead, with the [uppy-s3_multipart] gem on the backend. Your back-end
|
183
|
+
implementation is similar, just using `Shrine.uppy_s3_multipart` in place of
|
184
|
+
`Shrine.presign_endpoint`. Instructions can be found in uppy-s3_multipart
|
185
|
+
README.
|
186
|
+
|
179
187
|
## Strategy B (static)
|
180
188
|
|
181
189
|
* Basic user experience
|
@@ -385,6 +393,8 @@ setup] guide.
|
|
385
393
|
[Uppy]: https://uppy.io
|
386
394
|
[uppy aws s3]: https://uppy.io/docs/aws-s3/
|
387
395
|
[uppy aws-s3 cors]: https://uppy.io/docs/aws-s3/#S3-Bucket-configuration
|
396
|
+
[uppy aws s3 multipart]: https://uppy.io/docs/aws-s3/
|
397
|
+
[uppy-s3_multipart]: https://github.com/janko-m/uppy-s3_multipart
|
388
398
|
[Amazon S3 Data Consistency Model]: http://docs.aws.amazon.com/AmazonS3/latest/dev/Introduction.html#ConsistencyMode
|
389
399
|
[CORS guide]: http://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html
|
390
400
|
[CORS API]: https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#put_bucket_cors-instance_method
|
@@ -393,3 +403,4 @@ setup] guide.
|
|
393
403
|
[Minio]: https://minio.io
|
394
404
|
[minio setup]: https://shrinerb.com/rdoc/files/doc/testing_md.html#label-Minio
|
395
405
|
[metadata direct uploads]: https://github.com/shrinerb/shrine/blob/master/doc/metadata.md#direct-uploads
|
406
|
+
[content_disposition]: https://github.com/shrinerb/content_disposition
|
data/doc/metadata.md
CHANGED
@@ -26,6 +26,13 @@ uploader.extract_metadata(io) #=>
|
|
26
26
|
# }
|
27
27
|
```
|
28
28
|
|
29
|
+
By default these values are determined from the following attributes on the IO
|
30
|
+
object:
|
31
|
+
|
32
|
+
* `filename` – `io.original_filename` or `io.path`
|
33
|
+
* `mime_type` – `io.content_type`
|
34
|
+
* `size` – `io.size`
|
35
|
+
|
29
36
|
Note that you can also manually add or override metadata on upload by passing
|
30
37
|
the `:metadata` option to `Shrine#upload`:
|
31
38
|
|
@@ -181,21 +188,15 @@ least partially) retrieving file content from the storage, which could
|
|
181
188
|
potentially be expensive depending on the storage and the type of metadata
|
182
189
|
being extracted.
|
183
190
|
|
184
|
-
If you're just attaching files uploaded directly to local disk, there wouldn't
|
185
|
-
be any additional performance penalty for extracting metadata. However, if
|
186
|
-
you're attaching files uploaded directly to a cloud service like S3, retrieving
|
187
|
-
file content for metadata extraction would require an HTTP download. If you're
|
188
|
-
using just the `determine_mime_type` plugin, only a small portion of the file
|
189
|
-
will be downloaded, so the performance impact might not be so big. But in other
|
190
|
-
cases you might have to download the whole file.
|
191
|
-
|
192
191
|
There are two ways of extracting metadata from directly uploaded files. If you
|
193
192
|
want metadata to be automatically extracted on assignment (which is useful if
|
194
|
-
you want to validate the extracted metadata or have it immediately available
|
195
|
-
you can load the `restore_cached_data` plugin:
|
193
|
+
you want to validate the extracted metadata or have it immediately available
|
194
|
+
for any other reason), you can load the `restore_cached_data` plugin:
|
196
195
|
|
197
196
|
```rb
|
198
|
-
|
197
|
+
class ImageUploader < Shrine
|
198
|
+
plugin :restore_cached_data # automatically extract metadata from cached files on assignment
|
199
|
+
end
|
199
200
|
```
|
200
201
|
```rb
|
201
202
|
photo.image = '{"id":"ks9elsd.jpg","storage":"cache","metadata":{}}' # metadata is extracted
|
@@ -212,15 +213,13 @@ during background promotion using the `refresh_metadata` plugin (which the
|
|
212
213
|
`restore_cached_data` plugin uses internally):
|
213
214
|
|
214
215
|
```rb
|
215
|
-
Shrine
|
216
|
-
|
217
|
-
```rb
|
218
|
-
class MyUploader < Shrine
|
216
|
+
class ImageUploader < Shrine
|
217
|
+
plugin :refresh_metadata
|
219
218
|
plugin :processing
|
220
219
|
|
221
220
|
# this will be called in the background if using backgrounding plugin
|
222
221
|
process(:store) do |io, context|
|
223
|
-
io.refresh_metadata! # extracts metadata and updates `io.metadata`
|
222
|
+
io.refresh_metadata!(context) # extracts metadata and updates `io.metadata`
|
224
223
|
io
|
225
224
|
end
|
226
225
|
end
|
@@ -232,17 +231,24 @@ two approaches. For example, if you're attaching video files, you might want to
|
|
232
231
|
extract MIME type upfront and video-specific metadata in a background job, which
|
233
232
|
can be done as follows (provided that `backgrounding` plugin is used):
|
234
233
|
|
235
|
-
```rb
|
236
|
-
Shrine.plugin :restore_cached_data
|
237
|
-
```
|
238
234
|
```rb
|
239
235
|
class MyUploader < Shrine
|
240
236
|
plugin :determine_mime_type # this will be called in the foreground
|
237
|
+
plugin :restore_cached_data
|
238
|
+
plugin :refresh_metadata
|
239
|
+
plugin :add_metadata
|
241
240
|
plugin :processing
|
242
241
|
|
243
242
|
# this will be called in the background if using backgrounding plugin
|
244
243
|
process(:store) do |io, context|
|
245
|
-
|
244
|
+
io.refresh_metadata!(context)
|
245
|
+
io
|
246
|
+
end
|
247
|
+
|
248
|
+
add_metadata do |io, context|
|
249
|
+
next unless context[:action] == :store # this will be the case during promotion
|
250
|
+
|
251
|
+
Shrine.with_file(io) do |file|
|
246
252
|
# example of metadata extraction
|
247
253
|
movie = FFMPEG::Movie.new(file.path) # uses the streamio-ffmpeg gem
|
248
254
|
|
@@ -251,10 +257,49 @@ class MyUploader < Shrine
|
|
251
257
|
"resolution" => movie.resolution,
|
252
258
|
"frame_rate" => movie.frame_rate }
|
253
259
|
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
```
|
254
263
|
|
255
|
-
|
264
|
+
If you want to do both metadata extraction and file processing during
|
265
|
+
promotion, you can wrap both in an `UploadedFile#open` block to make
|
266
|
+
sure the file content is retrieved from the storage only once.
|
256
267
|
|
257
|
-
|
268
|
+
```rb
|
269
|
+
class MyUploader < Shrine
|
270
|
+
plugin :refresh_metadata
|
271
|
+
plugin :processing
|
272
|
+
|
273
|
+
process(:store) do |io, context|
|
274
|
+
io.open do |io, context|
|
275
|
+
io.refresh_metadata!(context)
|
276
|
+
|
277
|
+
original = io.download # reuses already open uploaded file
|
278
|
+
# ... processing ...
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
```
|
283
|
+
|
284
|
+
If you're dealing with large files, it's recommended to also use the `tempfile`
|
285
|
+
plugin to make sure the same copy of the uploaded file is used for metadata
|
286
|
+
extraction (`Shrine.with_file`) and processing (`UploadedFile#tempfile`).
|
287
|
+
|
288
|
+
```rb
|
289
|
+
Shrine.plugin :tempfile # load it globally so that it overrides `Shrine.with_file`
|
290
|
+
```
|
291
|
+
```rb
|
292
|
+
class MyUploader < Shrine
|
293
|
+
plugin :refresh_metadata
|
294
|
+
plugin :processing
|
295
|
+
|
296
|
+
process(:store) do |io, context|
|
297
|
+
io.open do |io, context|
|
298
|
+
io.refresh_metadata!(context)
|
299
|
+
|
300
|
+
original = io.tempfile # used the cached tempfile
|
301
|
+
# ... processing ...
|
302
|
+
end
|
258
303
|
end
|
259
304
|
end
|
260
305
|
```
|