carrierwave 1.3.4 → 3.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +278 -86
- data/lib/carrierwave/compatibility/paperclip.rb +4 -2
- data/lib/carrierwave/downloader/base.rb +101 -0
- data/lib/carrierwave/downloader/remote_file.rb +68 -0
- data/lib/carrierwave/locale/en.yml +9 -6
- data/lib/carrierwave/mount.rb +53 -61
- data/lib/carrierwave/mounter.rb +169 -77
- data/lib/carrierwave/orm/activerecord.rb +23 -58
- data/lib/carrierwave/processing/mini_magick.rb +137 -123
- data/lib/carrierwave/processing/rmagick.rb +47 -20
- data/lib/carrierwave/processing/vips.rb +315 -0
- data/lib/carrierwave/processing.rb +1 -0
- data/lib/carrierwave/sanitized_file.rb +91 -70
- data/lib/carrierwave/storage/abstract.rb +5 -5
- data/lib/carrierwave/storage/file.rb +6 -5
- data/lib/carrierwave/storage/fog.rb +114 -62
- data/lib/carrierwave/storage.rb +1 -0
- data/lib/carrierwave/test/matchers.rb +11 -7
- data/lib/carrierwave/uploader/cache.rb +40 -24
- data/lib/carrierwave/uploader/callbacks.rb +1 -1
- data/lib/carrierwave/uploader/configuration.rb +43 -20
- data/lib/carrierwave/uploader/content_type_allowlist.rb +62 -0
- data/lib/carrierwave/uploader/content_type_denylist.rb +65 -0
- data/lib/carrierwave/uploader/dimension.rb +66 -0
- data/lib/carrierwave/uploader/download.rb +2 -123
- data/lib/carrierwave/uploader/extension_allowlist.rb +63 -0
- data/lib/carrierwave/uploader/extension_denylist.rb +64 -0
- data/lib/carrierwave/uploader/file_size.rb +2 -2
- data/lib/carrierwave/uploader/mountable.rb +6 -0
- data/lib/carrierwave/uploader/processing.rb +45 -7
- data/lib/carrierwave/uploader/proxy.rb +17 -4
- data/lib/carrierwave/uploader/serialization.rb +1 -1
- data/lib/carrierwave/uploader/store.rb +73 -7
- data/lib/carrierwave/uploader/url.rb +7 -4
- data/lib/carrierwave/uploader/versions.rb +161 -111
- data/lib/carrierwave/uploader.rb +10 -17
- data/lib/carrierwave/utilities/file_name.rb +47 -0
- data/lib/carrierwave/utilities/uri.rb +14 -11
- data/lib/carrierwave/utilities.rb +1 -0
- data/lib/carrierwave/validations/active_model.rb +7 -9
- data/lib/carrierwave/version.rb +1 -1
- data/lib/carrierwave.rb +22 -17
- data/lib/generators/templates/{uploader.rb → uploader.rb.erb} +13 -4
- data/lib/generators/uploader_generator.rb +3 -3
- metadata +115 -44
- data/lib/carrierwave/uploader/content_type_blacklist.rb +0 -48
- data/lib/carrierwave/uploader/content_type_whitelist.rb +0 -48
- data/lib/carrierwave/uploader/extension_blacklist.rb +0 -51
- data/lib/carrierwave/uploader/extension_whitelist.rb +0 -52
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3fce89671ca96c66db403199f1eab005bdb208ae699bcd6c6d58d470ec337d96
|
|
4
|
+
data.tar.gz: 0047624b2e05641fbb2d65d97815726e9bc296fc8cdb53c37815ead2ce30d6e4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5f63f1e37da1f107660263cc2d4be4e09dd0076e12bf80bc057449ddbd288887210ae17392d4092ff240c9992be3819721e7665a72023e4b58a8e9d351434d37
|
|
7
|
+
data.tar.gz: 205220c3605f50f23379781d94c587aee68a75aa7d4d854a258d362983122115641482098e81574dd873acce90deeb124d01b24c9ff7970dc45c2cb3146a9bd1
|
data/README.md
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
This gem provides a simple and extremely flexible way to upload files from Ruby applications.
|
|
4
4
|
It works well with Rack based web applications, such as Ruby on Rails.
|
|
5
5
|
|
|
6
|
-
[](https://github.com/carrierwaveuploader/carrierwave/actions)
|
|
7
7
|
[](https://codeclimate.com/github/carrierwaveuploader/carrierwave)
|
|
8
8
|
[](https://dependabot.com/compatibility-score.html?dependency-name=carrierwave&package-manager=bundler&version-scheme=semver)
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
## Information
|
|
12
12
|
|
|
13
|
-
* RDoc documentation [available on RubyDoc.info](
|
|
13
|
+
* RDoc documentation [available on RubyDoc.info](https://rubydoc.info/gems/carrierwave)
|
|
14
14
|
* Source code [available on GitHub](http://github.com/carrierwaveuploader/carrierwave)
|
|
15
15
|
* More information, known limitations, and how-tos [available on the wiki](https://github.com/carrierwaveuploader/carrierwave/wiki)
|
|
16
16
|
|
|
@@ -30,13 +30,19 @@ $ gem install carrierwave
|
|
|
30
30
|
In Rails, add it to your Gemfile:
|
|
31
31
|
|
|
32
32
|
```ruby
|
|
33
|
-
gem 'carrierwave', '~>
|
|
33
|
+
gem 'carrierwave', '~> 3.0'
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
Finally, restart the server to apply the changes.
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
## Upgrading from 2.x or earlier
|
|
39
|
+
|
|
40
|
+
CarrierWave 3.0 comes with a change in the way of handling the file extension on conversion. This results in following issues if you use `process convert: :format` to change the file format:
|
|
41
|
+
|
|
42
|
+
- If you have it on the uploader itself (not within a version), the file extension of the cached file will change. That means if you serve both CarrierWave 2.x and 3.x simultaneously on the same workload (e.g. using blue-green deployment), a cache file stored by 2.x can't be retrieved by 3.x and vice versa.
|
|
43
|
+
- If you have it within a version, the file extension of the stored file will change. You need to perform `#recreate_versions!` to make it usable again.
|
|
44
|
+
|
|
45
|
+
To preserve the 2.x behavior, you can set `force_extension false` right after calling `process convert: :format`. See [#2659](https://github.com/carrierwaveuploader/carrierwave/pull/2659) for the detail.
|
|
40
46
|
|
|
41
47
|
## Getting Started
|
|
42
48
|
|
|
@@ -94,7 +100,7 @@ a migration:
|
|
|
94
100
|
Open your model file and mount the uploader:
|
|
95
101
|
|
|
96
102
|
```ruby
|
|
97
|
-
class User <
|
|
103
|
+
class User < ApplicationRecord
|
|
98
104
|
mount_uploader :avatar, AvatarUploader
|
|
99
105
|
end
|
|
100
106
|
```
|
|
@@ -157,7 +163,7 @@ Open your model file and mount the uploader:
|
|
|
157
163
|
|
|
158
164
|
|
|
159
165
|
```ruby
|
|
160
|
-
class User <
|
|
166
|
+
class User < ApplicationRecord
|
|
161
167
|
mount_uploaders :avatars, AvatarUploader
|
|
162
168
|
serialize :avatars, JSON # If you use SQLite, add this line.
|
|
163
169
|
end
|
|
@@ -190,6 +196,17 @@ u.avatars[0].current_path # => 'path/to/file.png'
|
|
|
190
196
|
u.avatars[0].identifier # => 'file.png'
|
|
191
197
|
```
|
|
192
198
|
|
|
199
|
+
If you want to preserve existing files on uploading new one, you can go like:
|
|
200
|
+
|
|
201
|
+
```erb
|
|
202
|
+
<% user.avatars.each do |avatar| %>
|
|
203
|
+
<%= hidden_field :user, :avatars, multiple: true, value: avatar.identifier %>
|
|
204
|
+
<% end %>
|
|
205
|
+
<%= form.file_field :avatars, multiple: true %>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Sorting avatars is supported as well by reordering `hidden_field`, an example using jQuery UI Sortable is available [here](https://github.com/carrierwaveuploader/carrierwave/wiki/How-to%3A-Add%2C-remove-and-reorder-images-using-multiple-file-upload).
|
|
209
|
+
|
|
193
210
|
## Changing the storage directory
|
|
194
211
|
|
|
195
212
|
In order to change where uploaded files are put, just override the `store_dir`
|
|
@@ -216,10 +233,24 @@ class MyUploader < CarrierWave::Uploader::Base
|
|
|
216
233
|
end
|
|
217
234
|
```
|
|
218
235
|
|
|
236
|
+
## Changing the filename
|
|
237
|
+
|
|
238
|
+
To change the filename of uploaded files, you can override `#filename` method in the uploader.
|
|
239
|
+
|
|
240
|
+
```ruby
|
|
241
|
+
class MyUploader < CarrierWave::Uploader::Base
|
|
242
|
+
def filename
|
|
243
|
+
"image.#{file.extension}" # If you upload 'file.jpg', you'll get 'image.jpg'
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Some old documentations (like [this](https://stackoverflow.com/a/5865117)) may instruct you to safeguard the filename value with `if original_filename`, but it's no longer necessary with CarrierWave 3.0 or later.
|
|
249
|
+
|
|
219
250
|
## Securing uploads
|
|
220
251
|
|
|
221
252
|
Certain files might be dangerous if uploaded to the wrong location, such as PHP
|
|
222
|
-
files or other script files. CarrierWave allows you to specify
|
|
253
|
+
files or other script files. CarrierWave allows you to specify an allowlist of
|
|
223
254
|
allowed extensions or content types.
|
|
224
255
|
|
|
225
256
|
If you're mounting the uploader, uploading a file with the wrong extension will
|
|
@@ -227,7 +258,7 @@ make the record invalid instead. Otherwise, an error is raised.
|
|
|
227
258
|
|
|
228
259
|
```ruby
|
|
229
260
|
class MyUploader < CarrierWave::Uploader::Base
|
|
230
|
-
def
|
|
261
|
+
def extension_allowlist
|
|
231
262
|
%w(jpg jpeg gif png)
|
|
232
263
|
end
|
|
233
264
|
end
|
|
@@ -238,29 +269,45 @@ Let's say we need an uploader that accepts only images. This can be done like th
|
|
|
238
269
|
|
|
239
270
|
```ruby
|
|
240
271
|
class MyUploader < CarrierWave::Uploader::Base
|
|
241
|
-
def
|
|
272
|
+
def content_type_allowlist
|
|
242
273
|
/image\//
|
|
243
274
|
end
|
|
244
275
|
end
|
|
245
276
|
```
|
|
246
277
|
|
|
247
|
-
You can use a
|
|
278
|
+
You can use a denylist to reject content types.
|
|
248
279
|
Let's say we need an uploader that reject JSON files. This can be done like this
|
|
249
280
|
|
|
250
281
|
```ruby
|
|
251
282
|
class NoJsonUploader < CarrierWave::Uploader::Base
|
|
252
|
-
def
|
|
283
|
+
def content_type_denylist
|
|
253
284
|
['application/text', 'application/json']
|
|
254
285
|
end
|
|
255
286
|
end
|
|
256
287
|
```
|
|
257
288
|
|
|
289
|
+
### CVE-2016-3714 (ImageTragick)
|
|
290
|
+
This version of CarrierWave has the ability to mitigate CVE-2016-3714. However, you **MUST** set a content_type_allowlist in your uploaders for this protection to be effective, and you **MUST** either disable ImageMagick's default SVG delegate or use the RSVG delegate for SVG processing.
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
A valid allowlist that will restrict your uploader to images only, and mitigate the CVE is:
|
|
294
|
+
|
|
295
|
+
```ruby
|
|
296
|
+
class MyUploader < CarrierWave::Uploader::Base
|
|
297
|
+
def content_type_allowlist
|
|
298
|
+
[/image\//]
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**WARNING**: A `content_type_allowlist` is the only form of allowlist or denylist supported by CarrierWave that can effectively mitigate against CVE-2016-3714. Use of `extension_allowlist` will not inspect the file headers, and thus still leaves your application open to the vulnerability.
|
|
304
|
+
|
|
258
305
|
### Filenames and unicode chars
|
|
259
306
|
|
|
260
307
|
Another security issue you should care for is the file names (see
|
|
261
308
|
[Ruby On Rails Security Guide](http://guides.rubyonrails.org/security.html#file-uploads)).
|
|
262
309
|
By default, CarrierWave provides only English letters, arabic numerals and some symbols as
|
|
263
|
-
|
|
310
|
+
allowlisted characters in the file name. If you want to support local scripts (Cyrillic letters, letters with diacritics and so on), you
|
|
264
311
|
have to override `sanitize_regexp` method. It should return regular expression which would match
|
|
265
312
|
all *non*-allowed symbols.
|
|
266
313
|
|
|
@@ -278,17 +325,8 @@ You no longer need to do this manually.
|
|
|
278
325
|
|
|
279
326
|
## Adding versions
|
|
280
327
|
|
|
281
|
-
Often you'll want to add different versions of the same file. The classic example is image thumbnails
|
|
282
|
-
|
|
283
|
-
*Note:* You must have Imagemagick and MiniMagick installed to do image resizing. MiniMagick is a Ruby interface for Imagemagick which is a C program. This is why MiniMagick fails on 'bundle install' without Imagemagick installed.
|
|
284
|
-
|
|
285
|
-
Some documentation refers to RMagick instead of MiniMagick but MiniMagick is recommended.
|
|
286
|
-
|
|
287
|
-
To install Imagemagick on OSX with homebrew type the following:
|
|
288
|
-
|
|
289
|
-
```
|
|
290
|
-
$ brew install imagemagick
|
|
291
|
-
```
|
|
328
|
+
Often you'll want to add different versions of the same file. The classic example is generating image thumbnails while preserving the original file to be used for high-quality representation.
|
|
329
|
+
In this section we'll explore how CarrierWave supports working with multiple versions. The image manipulation itself is covered in [another section](#manipulating-images).
|
|
292
330
|
|
|
293
331
|
```ruby
|
|
294
332
|
class MyUploader < CarrierWave::Uploader::Base
|
|
@@ -305,15 +343,13 @@ end
|
|
|
305
343
|
|
|
306
344
|
When this uploader is used, an uploaded image would be scaled to be no larger
|
|
307
345
|
than 800 by 800 pixels. The original aspect ratio will be kept.
|
|
308
|
-
A version called thumb is then created, which is scaled
|
|
309
|
-
to exactly 200 by 200 pixels.
|
|
310
346
|
|
|
311
|
-
|
|
312
|
-
|
|
347
|
+
A version called `:thumb` is then created, which is scaled
|
|
348
|
+
to exactly 200 by 200 pixels. The thumbnail uses `resize_to_fill` which makes sure
|
|
313
349
|
that the width and height specified are filled, only cropping
|
|
314
350
|
if the aspect ratio requires it.
|
|
315
351
|
|
|
316
|
-
The uploader could be used like this:
|
|
352
|
+
The above uploader could be used like this:
|
|
317
353
|
|
|
318
354
|
```ruby
|
|
319
355
|
uploader = AvatarUploader.new
|
|
@@ -326,6 +362,24 @@ uploader.thumb.url # => '/url/to/thumb_my_file.png' # size: 200x200
|
|
|
326
362
|
One important thing to remember is that process is called *before* versions are
|
|
327
363
|
created. This can cut down on processing cost.
|
|
328
364
|
|
|
365
|
+
### Conditional processing
|
|
366
|
+
|
|
367
|
+
If you want to use conditional process, you can only use `if` statement.
|
|
368
|
+
|
|
369
|
+
See `carrierwave/uploader/processing.rb` for details.
|
|
370
|
+
|
|
371
|
+
```ruby
|
|
372
|
+
class MyUploader < CarrierWave::Uploader::Base
|
|
373
|
+
process :scale => [200, 200], :if => :image?
|
|
374
|
+
|
|
375
|
+
def image?(carrier_wave_sanitized_file)
|
|
376
|
+
true
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Nested versions
|
|
382
|
+
|
|
329
383
|
It is possible to nest versions within versions:
|
|
330
384
|
|
|
331
385
|
```ruby
|
|
@@ -362,7 +416,7 @@ private
|
|
|
362
416
|
end
|
|
363
417
|
|
|
364
418
|
def is_landscape? picture
|
|
365
|
-
image = MiniMagick::Image.
|
|
419
|
+
image = MiniMagick::Image.new(picture.path)
|
|
366
420
|
image[:width] > image[:height]
|
|
367
421
|
end
|
|
368
422
|
|
|
@@ -392,8 +446,27 @@ class MyUploader < CarrierWave::Uploader::Base
|
|
|
392
446
|
end
|
|
393
447
|
```
|
|
394
448
|
|
|
395
|
-
|
|
396
|
-
|
|
449
|
+
### Customizing version filenames
|
|
450
|
+
|
|
451
|
+
CarrierWave supports [customization of filename](#changing-the-filename) by overriding an uploader's
|
|
452
|
+
#filename method, but this doesn't work for versions because of the limitation on how CarrierWave
|
|
453
|
+
re-constructs the filename on retrieval of the stored file.
|
|
454
|
+
Instead, you can override `#full_filename` with providing a version-aware name.
|
|
455
|
+
|
|
456
|
+
```ruby
|
|
457
|
+
class MyUploader < CarrierWave::Uploader::Base
|
|
458
|
+
version :thumb do
|
|
459
|
+
def full_filename(for_file)
|
|
460
|
+
'thumb.png'
|
|
461
|
+
end
|
|
462
|
+
process convert: 'png'
|
|
463
|
+
end
|
|
464
|
+
end
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
Please note that `#full_filename` mustn't be constructed based on a dynamic value
|
|
468
|
+
that can change from the time of store and time of retrieval, since it will result in
|
|
469
|
+
being unable to retrieve a file previously stored.
|
|
397
470
|
|
|
398
471
|
## Making uploads work across form redisplays
|
|
399
472
|
|
|
@@ -478,6 +551,17 @@ failures automatically with attribute validation errors. If you aren't, or you
|
|
|
478
551
|
disable CarrierWave's `validate_download` option, you'll need to handle those
|
|
479
552
|
errors yourself.
|
|
480
553
|
|
|
554
|
+
### Retry option for download from remote location
|
|
555
|
+
If you want to retry the download from the Remote URL, enable the download_retry_count option, an error occurs during download, it will try to execute the specified number of times.
|
|
556
|
+
This option is effective when the remote destination is unstable.
|
|
557
|
+
|
|
558
|
+
```rb
|
|
559
|
+
CarrierWave.configure do |config|
|
|
560
|
+
config.download_retry_count = 3 # Default 0
|
|
561
|
+
config.download_retry_wait_time = 3 # Default 5
|
|
562
|
+
end
|
|
563
|
+
```
|
|
564
|
+
|
|
481
565
|
## Providing a default URL
|
|
482
566
|
|
|
483
567
|
In many cases, especially when working with images, it might be a good idea to
|
|
@@ -575,14 +659,17 @@ end
|
|
|
575
659
|
## Testing with CarrierWave
|
|
576
660
|
|
|
577
661
|
It's a good idea to test your uploaders in isolation. In order to speed up your
|
|
578
|
-
tests, it's recommended to switch off processing in your tests, and to use the
|
|
579
|
-
|
|
662
|
+
tests, it's recommended to switch off processing in your tests, and to use the file storage.
|
|
663
|
+
Also, you can disable SSRF protection at your own risk using the `skip_ssrf_protection` configuration.
|
|
664
|
+
|
|
665
|
+
In Rails you could do that by adding an initializer with:
|
|
580
666
|
|
|
581
667
|
```ruby
|
|
582
668
|
if Rails.env.test? or Rails.env.cucumber?
|
|
583
669
|
CarrierWave.configure do |config|
|
|
584
670
|
config.storage = :file
|
|
585
671
|
config.enable_processing = false
|
|
672
|
+
config.skip_ssrf_protection = true
|
|
586
673
|
end
|
|
587
674
|
end
|
|
588
675
|
```
|
|
@@ -651,7 +738,6 @@ If you want to use fog you must add in your CarrierWave initializer the
|
|
|
651
738
|
following lines
|
|
652
739
|
|
|
653
740
|
```ruby
|
|
654
|
-
config.fog_provider = 'fog' # 'fog/aws' etc. Defaults to 'fog'
|
|
655
741
|
config.fog_credentials = { ... } # Provider specific credentials
|
|
656
742
|
```
|
|
657
743
|
|
|
@@ -669,7 +755,6 @@ You can also pass in additional options, as documented fully in lib/carrierwave/
|
|
|
669
755
|
|
|
670
756
|
```ruby
|
|
671
757
|
CarrierWave.configure do |config|
|
|
672
|
-
config.fog_provider = 'fog/aws' # required
|
|
673
758
|
config.fog_credentials = {
|
|
674
759
|
provider: 'AWS', # required
|
|
675
760
|
aws_access_key_id: 'xxx', # required unless using use_iam_profile
|
|
@@ -682,6 +767,13 @@ CarrierWave.configure do |config|
|
|
|
682
767
|
config.fog_directory = 'name_of_bucket' # required
|
|
683
768
|
config.fog_public = false # optional, defaults to true
|
|
684
769
|
config.fog_attributes = { cache_control: "public, max-age=#{365.days.to_i}" } # optional, defaults to {}
|
|
770
|
+
# Use this if you have AWS S3 ACLs disabled.
|
|
771
|
+
# config.fog_attributes = { 'x-amz-acl' => 'bucket-owner-full-control' }
|
|
772
|
+
# Use this if you have Google Cloud Storage uniform bucket-level access enabled.
|
|
773
|
+
# config.fog_attributes = { uniform: true }
|
|
774
|
+
# For an application which utilizes multiple servers but does not need caches persisted across requests,
|
|
775
|
+
# uncomment the line :file instead of the default :storage. Otherwise, it will use AWS as the temp cache store.
|
|
776
|
+
# config.cache_storage = :file
|
|
685
777
|
end
|
|
686
778
|
```
|
|
687
779
|
|
|
@@ -695,6 +787,14 @@ end
|
|
|
695
787
|
|
|
696
788
|
That's it! You can still use the `CarrierWave::Uploader#url` method to return the url to the file on Amazon S3.
|
|
697
789
|
|
|
790
|
+
**Note**: for Carrierwave to work properly it needs credentials with the following permissions:
|
|
791
|
+
|
|
792
|
+
* `s3:ListBucket`
|
|
793
|
+
* `s3:PutObject`
|
|
794
|
+
* `s3:GetObject`
|
|
795
|
+
* `s3:DeleteObject`
|
|
796
|
+
* `s3:PutObjectAcl`
|
|
797
|
+
|
|
698
798
|
## Using Rackspace Cloud Files
|
|
699
799
|
|
|
700
800
|
[Fog](http://github.com/fog/fog) is used to support Rackspace Cloud Files. Ensure you have it in your Gemfile:
|
|
@@ -704,13 +804,12 @@ gem "fog"
|
|
|
704
804
|
```
|
|
705
805
|
|
|
706
806
|
You'll need to configure a directory (also known as a container), username and API key in the initializer.
|
|
707
|
-
For the sake of performance it is assumed that the directory already exists, so please create it if
|
|
807
|
+
For the sake of performance it is assumed that the directory already exists, so please create it if needs to be.
|
|
708
808
|
|
|
709
809
|
Using a US-based account:
|
|
710
810
|
|
|
711
811
|
```ruby
|
|
712
812
|
CarrierWave.configure do |config|
|
|
713
|
-
config.fog_provider = "fog/rackspace/storage" # optional, defaults to "fog"
|
|
714
813
|
config.fog_credentials = {
|
|
715
814
|
provider: 'Rackspace',
|
|
716
815
|
rackspace_username: 'xxxxxx',
|
|
@@ -725,7 +824,6 @@ Using a UK-based account:
|
|
|
725
824
|
|
|
726
825
|
```ruby
|
|
727
826
|
CarrierWave.configure do |config|
|
|
728
|
-
config.fog_provider = "fog/rackspace/storage" # optional, defaults to "fog"
|
|
729
827
|
config.fog_credentials = {
|
|
730
828
|
provider: 'Rackspace',
|
|
731
829
|
rackspace_username: 'xxxxxx',
|
|
@@ -756,31 +854,41 @@ end
|
|
|
756
854
|
That's it! You can still use the `CarrierWave::Uploader#url` method to return
|
|
757
855
|
the url to the file on Rackspace Cloud Files.
|
|
758
856
|
|
|
759
|
-
## Using Google Storage
|
|
857
|
+
## Using Google Cloud Storage
|
|
760
858
|
|
|
761
|
-
[Fog](http://github.com/fog/fog-google) is used to support Google Storage
|
|
859
|
+
[Fog](http://github.com/fog/fog-google) is used to support Google Cloud Storage. Ensure you have it in your Gemfile:
|
|
762
860
|
|
|
763
861
|
```ruby
|
|
764
862
|
gem "fog-google"
|
|
765
|
-
gem "google-api-client", "> 0.8.5", "< 0.9"
|
|
766
|
-
gem "mime-types"
|
|
767
863
|
```
|
|
768
864
|
|
|
769
|
-
You'll need to configure a directory (also known as a bucket)
|
|
770
|
-
For the sake of performance it is assumed that the directory already exists, so please create it if
|
|
865
|
+
You'll need to configure a directory (also known as a bucket) and the credentials in the initializer.
|
|
866
|
+
For the sake of performance it is assumed that the directory already exists, so please create it if needs to be.
|
|
771
867
|
|
|
772
868
|
Please read the [fog-google README](https://github.com/fog/fog-google/blob/master/README.md) on how to get credentials.
|
|
773
869
|
|
|
870
|
+
For Google Storage JSON API (recommended):
|
|
871
|
+
```ruby
|
|
872
|
+
CarrierWave.configure do |config|
|
|
873
|
+
config.fog_credentials = {
|
|
874
|
+
provider: 'Google',
|
|
875
|
+
google_project: 'my-project',
|
|
876
|
+
google_json_key_string: 'xxxxxx'
|
|
877
|
+
# or use google_json_key_location if using an actual file
|
|
878
|
+
}
|
|
879
|
+
config.fog_directory = 'google_cloud_storage_bucket_name'
|
|
880
|
+
end
|
|
881
|
+
```
|
|
774
882
|
|
|
883
|
+
For Google Storage XML API:
|
|
775
884
|
```ruby
|
|
776
885
|
CarrierWave.configure do |config|
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
config.fog_directory = 'name_of_directory'
|
|
886
|
+
config.fog_credentials = {
|
|
887
|
+
provider: 'Google',
|
|
888
|
+
google_storage_access_key_id: 'xxxxxx',
|
|
889
|
+
google_storage_secret_access_key: 'yyyyyy'
|
|
890
|
+
}
|
|
891
|
+
config.fog_directory = 'google_cloud_storage_bucket_name'
|
|
784
892
|
end
|
|
785
893
|
```
|
|
786
894
|
|
|
@@ -833,12 +941,48 @@ CarrierWave.configure do |config|
|
|
|
833
941
|
end
|
|
834
942
|
```
|
|
835
943
|
|
|
836
|
-
##
|
|
944
|
+
## Manipulating images
|
|
837
945
|
|
|
838
946
|
If you're uploading images, you'll probably want to manipulate them in some way,
|
|
839
|
-
you might want to create thumbnail images for example.
|
|
840
|
-
|
|
841
|
-
|
|
947
|
+
you might want to create thumbnail images for example.
|
|
948
|
+
|
|
949
|
+
### Using MiniMagick
|
|
950
|
+
|
|
951
|
+
MiniMagick performs all the operations using the 'convert' CLI which is part of the standard ImageMagick kit.
|
|
952
|
+
This allows you to have the power of ImageMagick without having to worry about installing
|
|
953
|
+
all the RMagick libraries, it often results in higher memory footprint.
|
|
954
|
+
|
|
955
|
+
See the MiniMagick site for more details:
|
|
956
|
+
|
|
957
|
+
https://github.com/minimagick/minimagick
|
|
958
|
+
|
|
959
|
+
To install Imagemagick on OSX with homebrew type the following:
|
|
960
|
+
|
|
961
|
+
```
|
|
962
|
+
$ brew install imagemagick
|
|
963
|
+
```
|
|
964
|
+
|
|
965
|
+
And the ImageMagick command line options for more for what's on offer:
|
|
966
|
+
|
|
967
|
+
http://www.imagemagick.org/script/command-line-options.php
|
|
968
|
+
|
|
969
|
+
Currently, the MiniMagick carrierwave processor provides exactly the same methods as
|
|
970
|
+
for the RMagick processor.
|
|
971
|
+
|
|
972
|
+
```ruby
|
|
973
|
+
class AvatarUploader < CarrierWave::Uploader::Base
|
|
974
|
+
include CarrierWave::MiniMagick
|
|
975
|
+
|
|
976
|
+
process resize_to_fill: [200, 200]
|
|
977
|
+
end
|
|
978
|
+
```
|
|
979
|
+
|
|
980
|
+
See `carrierwave/processing/mini_magick.rb` for details.
|
|
981
|
+
|
|
982
|
+
### Using RMagick
|
|
983
|
+
|
|
984
|
+
CarrierWave also comes with support for RMagick, a well-known image processing library.
|
|
985
|
+
To use it, you'll need to include this in your Uploader:
|
|
842
986
|
|
|
843
987
|
```ruby
|
|
844
988
|
class AvatarUploader < CarrierWave::Uploader::Base
|
|
@@ -851,7 +995,6 @@ The RMagick module gives you a few methods, like
|
|
|
851
995
|
way. You can set a `process` callback, which will call that method any time a
|
|
852
996
|
file is uploaded.
|
|
853
997
|
There is a demonstration of convert here.
|
|
854
|
-
Convert will only work if the file has the same file extension, thus the use of the filename method.
|
|
855
998
|
|
|
856
999
|
```ruby
|
|
857
1000
|
class AvatarUploader < CarrierWave::Uploader::Base
|
|
@@ -859,40 +1002,59 @@ class AvatarUploader < CarrierWave::Uploader::Base
|
|
|
859
1002
|
|
|
860
1003
|
process resize_to_fill: [200, 200]
|
|
861
1004
|
process convert: 'png'
|
|
862
|
-
|
|
863
|
-
def filename
|
|
864
|
-
super.chomp(File.extname(super)) + '.png' if original_filename.present?
|
|
865
|
-
end
|
|
866
1005
|
end
|
|
867
1006
|
```
|
|
868
1007
|
|
|
869
1008
|
Check out the manipulate! method, which makes it easy for you to write your own
|
|
870
1009
|
manipulation methods.
|
|
871
1010
|
|
|
872
|
-
|
|
1011
|
+
### Using Vips
|
|
873
1012
|
|
|
874
|
-
|
|
875
|
-
command which is part of the standard ImageMagick kit. This allows you to have the power
|
|
876
|
-
of ImageMagick without having to worry about installing all the RMagick libraries.
|
|
1013
|
+
CarrierWave version 2.2.0 added support for the `libvips` image processing library, through [ImageProcessing::Vips](https://github.com/janko/image_processing/blob/master/doc/vips.md). Its functionality matches that of the RMagick and MiniMagick processors, but it uses less memory and offers [faster processing](https://github.com/libvips/libvips/wiki/Speed-and-memory-use). To use the Vips processing module you must first install `libvips`, for example:
|
|
877
1014
|
|
|
878
|
-
|
|
1015
|
+
````bash
|
|
1016
|
+
$ sudo apt install libvips
|
|
1017
|
+
````
|
|
879
1018
|
|
|
880
|
-
|
|
1019
|
+
You also need to tell your uploader to use Vips:
|
|
881
1020
|
|
|
882
|
-
|
|
1021
|
+
````ruby
|
|
1022
|
+
class ImageFileUploader < CarrierWave::Uploader::Base
|
|
1023
|
+
include CarrierWave::Vips
|
|
1024
|
+
end
|
|
1025
|
+
````
|
|
883
1026
|
|
|
884
|
-
|
|
1027
|
+
### List of available processing methods:
|
|
885
1028
|
|
|
886
|
-
|
|
887
|
-
|
|
1029
|
+
> [!NOTE]
|
|
1030
|
+
> While the intention is to provide uniform interfaces to all three processing libraries the availability and implementation of processing methods can <a href="supported-processing-methods">vary slightly between them</a>.
|
|
888
1031
|
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
1032
|
+
- `convert` - Changes the image encoding format to the given format (eg. jpg). This operation is treated specially to trigger the change of the file extension, so it matches with the format of the resulting file.
|
|
1033
|
+
- `resize_to_limit` - Resize the image to fit within the specified dimensions while retaining the original aspect ratio. Will only resize the image if it is larger than the specified dimensions. The resulting image may be shorter or narrower than specified in the smaller dimension but will not be larger than the specified values.
|
|
1034
|
+
- `resize_to_fit` - Resize the image to fit within the specified dimensions while retaining the original aspect ratio. The image may be shorter or narrower than specified in the smaller dimension but will not be larger than the specified values.
|
|
1035
|
+
- `resize_to_fill` - Resize the image to fit within the specified dimensions while retaining the aspect ratio of the original image. If necessary, crop the image in the larger dimension. Optionally, a "gravity" may be specified, for example "Center", or "NorthEast".
|
|
1036
|
+
- `resize_and_pad` - Resize the image to fit within the specified dimensions while retaining the original aspect ratio. If necessary, will pad the remaining area with the given color, which defaults to transparent (for gif and png, white for jpeg). Optionally, a "gravity" may be specified, as above.
|
|
1037
|
+
- `crop` - Crop the image to the contents of a box with the specified height and width, positioned a given number of pixels from the top and left. The original image edge will be retained should the bottom and/or right edge of the box fall outside the image bounds.
|
|
892
1038
|
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
1039
|
+
#### Supported processing methods
|
|
1040
|
+
|
|
1041
|
+
The following table shows which processing methods are supported by each processing library, and which parameters they accept:
|
|
1042
|
+
|
|
1043
|
+
Method|RMagick|MiniMagick|Vips
|
|
1044
|
+
------|-----------------|-----------------|-----------------|
|
|
1045
|
+
`convert`|`format`|`format`, `page`<sup>1</sup>|`format`, `page`<sup>1</sup>
|
|
1046
|
+
`resize_to_limit`|`width`, `height`|`width`, `height`|`width`, `height`
|
|
1047
|
+
`resize_to_fit`|`width`, `height`|`width`, `height`|`width`, `height`
|
|
1048
|
+
`resize_to_fill`|`width`, `height`, `gravity`<sup>2</sup>|`width`, `height`, `gravity`<sup>2</sup>|`width`, `height`
|
|
1049
|
+
`resize_and_pad`|`width`, `height`, `background`, `gravity`<sup>2</sup>|`width`, `height`, `background`, `gravity`<sup>2</sup>|`width`, `height`, `background`, `gravity`<sup>2</sup>
|
|
1050
|
+
`resize_to_geometry_string`|`geometry_string`<sup>3</sup>|*not implemented*|*not implemented*
|
|
1051
|
+
`crop`|`left`, `top`, `width`, `height`|`left`, `top`, `width`, `height`|`left`, `top`, `width`, `height`
|
|
1052
|
+
|
|
1053
|
+
<sup>1</sup>`page` refers to the page number when converting from PDF, frame number when converting from GIF, and layer number when converting from PSD.
|
|
1054
|
+
|
|
1055
|
+
<sup>2</sup>`gravity` refers to an image position given as one of `Center`, `North`, `NorthWest`, `West`, `SouthWest`, `South`, `SouthEast`, `East`, or `NorthEast`.
|
|
1056
|
+
|
|
1057
|
+
<sup>3</sup>`geometry_string` is an [ImageMagick geometry string](https://rmagick.github.io/imusage.html#geometry).
|
|
896
1058
|
|
|
897
1059
|
## Migrating from Paperclip
|
|
898
1060
|
|
|
@@ -924,14 +1086,17 @@ errors:
|
|
|
924
1086
|
carrierwave_processing_error: failed to be processed
|
|
925
1087
|
carrierwave_integrity_error: is not of an allowed file type
|
|
926
1088
|
carrierwave_download_error: could not be downloaded
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
mini_magick_processing_error: "Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: %{e}"
|
|
1089
|
+
extension_allowlist_error: "You are not allowed to upload %{extension} files, allowed types: %{allowed_types}"
|
|
1090
|
+
extension_denylist_error: "You are not allowed to upload %{extension} files, prohibited types: %{prohibited_types}"
|
|
1091
|
+
content_type_allowlist_error: "You are not allowed to upload %{content_type} files, allowed types: %{allowed_types}"
|
|
1092
|
+
content_type_denylist_error: "You are not allowed to upload %{content_type} files"
|
|
1093
|
+
processing_error: "Failed to manipulate, maybe it is not an image?"
|
|
933
1094
|
min_size_error: "File size should be greater than %{min_size}"
|
|
934
1095
|
max_size_error: "File size should be less than %{max_size}"
|
|
1096
|
+
min_width_error: "Image width should be greater than %{min_width}px"
|
|
1097
|
+
max_width_error: "Image width should be less than %{max_width}px"
|
|
1098
|
+
min_height_error: "Image height should be greater than %{min_height}px"
|
|
1099
|
+
max_height_error: "Image height should be less than %{max_height}px"
|
|
935
1100
|
```
|
|
936
1101
|
|
|
937
1102
|
The [`carrierwave-i18n`](https://github.com/carrierwaveuploader/carrierwave-i18n)
|
|
@@ -975,12 +1140,12 @@ end
|
|
|
975
1140
|
Will add these callbacks:
|
|
976
1141
|
|
|
977
1142
|
```ruby
|
|
978
|
-
after_save :store_avatar!
|
|
979
1143
|
before_save :write_avatar_identifier
|
|
1144
|
+
after_save :store_previous_changes_for_avatar
|
|
980
1145
|
after_commit :remove_avatar!, on: :destroy
|
|
981
1146
|
after_commit :mark_remove_avatar_false, on: :update
|
|
982
|
-
after_save :store_previous_changes_for_avatar
|
|
983
1147
|
after_commit :remove_previously_stored_avatar, on: :update
|
|
1148
|
+
after_commit :store_avatar!, on: [:create, :update]
|
|
984
1149
|
```
|
|
985
1150
|
|
|
986
1151
|
If you want to skip any of these callbacks (eg. you want to keep the existing
|
|
@@ -994,13 +1159,40 @@ class User
|
|
|
994
1159
|
end
|
|
995
1160
|
```
|
|
996
1161
|
|
|
1162
|
+
## Uploader Callbacks
|
|
1163
|
+
|
|
1164
|
+
In addition to the ActiveRecord callbacks described above, uploaders also have callbacks.
|
|
1165
|
+
|
|
1166
|
+
```ruby
|
|
1167
|
+
class MyUploader < ::CarrierWave::Uploader::Base
|
|
1168
|
+
before :remove, :log_removal
|
|
1169
|
+
private
|
|
1170
|
+
def log_removal
|
|
1171
|
+
::Rails.logger.info(format('Deleting file on S3: %s', @file))
|
|
1172
|
+
end
|
|
1173
|
+
end
|
|
1174
|
+
```
|
|
1175
|
+
|
|
1176
|
+
Uploader callbacks can be `before` or `after` the following events:
|
|
1177
|
+
|
|
1178
|
+
```
|
|
1179
|
+
cache
|
|
1180
|
+
process
|
|
1181
|
+
remove
|
|
1182
|
+
retrieve_from_cache
|
|
1183
|
+
retrieve_from_store
|
|
1184
|
+
store
|
|
1185
|
+
```
|
|
1186
|
+
|
|
997
1187
|
## Contributing to CarrierWave
|
|
998
1188
|
|
|
999
1189
|
See [CONTRIBUTING.md](https://github.com/carrierwaveuploader/carrierwave/blob/master/CONTRIBUTING.md)
|
|
1000
1190
|
|
|
1001
1191
|
## License
|
|
1002
1192
|
|
|
1003
|
-
|
|
1193
|
+
The MIT License (MIT)
|
|
1194
|
+
|
|
1195
|
+
Copyright (c) 2008 Jonas Nicklas
|
|
1004
1196
|
|
|
1005
1197
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
1006
1198
|
a copy of this software and associated documentation files (the
|
|
@@ -56,10 +56,11 @@ module CarrierWave
|
|
|
56
56
|
:basename => lambda{|u, f| u.filename.gsub(/#{File.extname(u.filename)}$/, "") },
|
|
57
57
|
:extension => lambda{|u, d| File.extname(u.filename).gsub(/^\.+/, "")},
|
|
58
58
|
:class => lambda{|u, f| u.model.class.name.underscore.pluralize}
|
|
59
|
-
}
|
|
59
|
+
}.freeze
|
|
60
60
|
|
|
61
61
|
included do
|
|
62
62
|
attr_accessor :filename
|
|
63
|
+
|
|
63
64
|
class_attribute :mappings
|
|
64
65
|
self.mappings ||= DEFAULT_MAPPINGS.dup
|
|
65
66
|
end
|
|
@@ -92,7 +93,8 @@ module CarrierWave
|
|
|
92
93
|
end
|
|
93
94
|
end
|
|
94
95
|
|
|
95
|
-
|
|
96
|
+
private
|
|
97
|
+
|
|
96
98
|
def interpolate_paperclip_path(path)
|
|
97
99
|
mappings.each_pair.inject(path) do |agg, pair|
|
|
98
100
|
agg.gsub(":#{pair[0]}") { pair[1].call(self, self.paperclip_style).to_s }
|