carrierwave 2.2.2 → 3.1.0
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 +180 -62
- data/lib/carrierwave/compatibility/paperclip.rb +4 -2
- data/lib/carrierwave/downloader/base.rb +28 -14
- data/lib/carrierwave/downloader/remote_file.rb +13 -10
- data/lib/carrierwave/locale/en.yml +5 -3
- data/lib/carrierwave/mount.rb +36 -50
- data/lib/carrierwave/mounter.rb +118 -50
- data/lib/carrierwave/orm/activerecord.rb +21 -62
- data/lib/carrierwave/processing/mini_magick.rb +45 -14
- data/lib/carrierwave/processing/rmagick.rb +47 -20
- data/lib/carrierwave/processing/vips.rb +43 -12
- data/lib/carrierwave/sanitized_file.rb +58 -77
- data/lib/carrierwave/storage/abstract.rb +5 -5
- data/lib/carrierwave/storage/file.rb +6 -5
- data/lib/carrierwave/storage/fog.rb +86 -65
- data/lib/carrierwave/test/matchers.rb +11 -7
- data/lib/carrierwave/uploader/cache.rb +19 -11
- data/lib/carrierwave/uploader/callbacks.rb +1 -1
- data/lib/carrierwave/uploader/configuration.rb +18 -8
- data/lib/carrierwave/uploader/{content_type_whitelist.rb → content_type_allowlist.rb} +18 -16
- data/lib/carrierwave/uploader/{content_type_blacklist.rb → content_type_denylist.rb} +20 -15
- data/lib/carrierwave/uploader/dimension.rb +66 -0
- data/lib/carrierwave/uploader/{extension_whitelist.rb → extension_allowlist.rb} +17 -15
- data/lib/carrierwave/uploader/{extension_blacklist.rb → extension_denylist.rb} +19 -14
- data/lib/carrierwave/uploader/file_size.rb +2 -2
- data/lib/carrierwave/uploader/processing.rb +45 -7
- data/lib/carrierwave/uploader/proxy.rb +16 -3
- data/lib/carrierwave/uploader/store.rb +70 -6
- data/lib/carrierwave/uploader/url.rb +1 -1
- data/lib/carrierwave/uploader/versions.rb +158 -138
- data/lib/carrierwave/uploader.rb +10 -8
- 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 +4 -6
- data/lib/carrierwave/version.rb +1 -1
- data/lib/carrierwave.rb +18 -17
- data/lib/generators/templates/{uploader.rb → uploader.rb.erb} +1 -1
- data/lib/generators/uploader_generator.rb +3 -3
- metadata +37 -63
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 418e6b0903adc403510724ba7a5764e8edaa5b4bc96d5313e8f01572bf26ceac
|
4
|
+
data.tar.gz: 0bbac560a7928ce059afccb2280a1f77d17c9bca418a3f471097a3e3375fc6d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 253d7d3f2e78fd169e347042c6eae2d5ab70f1383dc159988387215cb669ca905232817484f168816c21bcfb6733221a69c6ae02d7a463df920446ee53ae8efd
|
7
|
+
data.tar.gz: 7640c8c67f2bb11025a42c9b05752a167a3da4d3452dc3359ffc51e5cb5ea8460fd23be401446734daa573e77f9a0639b7f2cf053288d8c5360e63907a80f08c
|
data/README.md
CHANGED
@@ -10,7 +10,7 @@ It works well with Rack based web applications, such as Ruby on Rails.
|
|
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
|
|
@@ -227,6 +233,20 @@ class MyUploader < CarrierWave::Uploader::Base
|
|
227
233
|
end
|
228
234
|
```
|
229
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
|
+
|
230
250
|
## Securing uploads
|
231
251
|
|
232
252
|
Certain files might be dangerous if uploaded to the wrong location, such as PHP
|
@@ -305,17 +325,8 @@ You no longer need to do this manually.
|
|
305
325
|
|
306
326
|
## Adding versions
|
307
327
|
|
308
|
-
Often you'll want to add different versions of the same file. The classic example is image thumbnails
|
309
|
-
|
310
|
-
*Note:* You must have Imagemagick installed to do image resizing.
|
311
|
-
|
312
|
-
Some documentation refers to RMagick instead of MiniMagick but MiniMagick is recommended.
|
313
|
-
|
314
|
-
To install Imagemagick on OSX with homebrew type the following:
|
315
|
-
|
316
|
-
```
|
317
|
-
$ brew install imagemagick
|
318
|
-
```
|
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).
|
319
330
|
|
320
331
|
```ruby
|
321
332
|
class MyUploader < CarrierWave::Uploader::Base
|
@@ -351,17 +362,7 @@ uploader.thumb.url # => '/url/to/thumb_my_file.png' # size: 200x200
|
|
351
362
|
One important thing to remember is that process is called *before* versions are
|
352
363
|
created. This can cut down on processing cost.
|
353
364
|
|
354
|
-
###
|
355
|
-
|
356
|
-
- `convert` - Changes the image encoding format to the given format, eg. jpg
|
357
|
-
- `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.
|
358
|
-
- `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.
|
359
|
-
- `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".
|
360
|
-
- `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.
|
361
|
-
|
362
|
-
See `carrierwave/processing/mini_magick.rb` for details.
|
363
|
-
|
364
|
-
### conditional process
|
365
|
+
### Conditional processing
|
365
366
|
|
366
367
|
If you want to use conditional process, you can only use `if` statement.
|
367
368
|
|
@@ -445,8 +446,27 @@ class MyUploader < CarrierWave::Uploader::Base
|
|
445
446
|
end
|
446
447
|
```
|
447
448
|
|
448
|
-
|
449
|
-
|
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.
|
450
470
|
|
451
471
|
## Making uploads work across form redisplays
|
452
472
|
|
@@ -531,6 +551,17 @@ failures automatically with attribute validation errors. If you aren't, or you
|
|
531
551
|
disable CarrierWave's `validate_download` option, you'll need to handle those
|
532
552
|
errors yourself.
|
533
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
|
+
|
534
565
|
## Providing a default URL
|
535
566
|
|
536
567
|
In many cases, especially when working with images, it might be a good idea to
|
@@ -628,14 +659,17 @@ end
|
|
628
659
|
## Testing with CarrierWave
|
629
660
|
|
630
661
|
It's a good idea to test your uploaders in isolation. In order to speed up your
|
631
|
-
tests, it's recommended to switch off processing in your tests, and to use the
|
632
|
-
|
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:
|
633
666
|
|
634
667
|
```ruby
|
635
668
|
if Rails.env.test? or Rails.env.cucumber?
|
636
669
|
CarrierWave.configure do |config|
|
637
670
|
config.storage = :file
|
638
671
|
config.enable_processing = false
|
672
|
+
config.skip_ssrf_protection = true
|
639
673
|
end
|
640
674
|
end
|
641
675
|
```
|
@@ -733,6 +767,10 @@ CarrierWave.configure do |config|
|
|
733
767
|
config.fog_directory = 'name_of_bucket' # required
|
734
768
|
config.fog_public = false # optional, defaults to true
|
735
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 }
|
736
774
|
# For an application which utilizes multiple servers but does not need caches persisted across requests,
|
737
775
|
# uncomment the line :file instead of the default :storage. Otherwise, it will use AWS as the temp cache store.
|
738
776
|
# config.cache_storage = :file
|
@@ -766,7 +804,7 @@ gem "fog"
|
|
766
804
|
```
|
767
805
|
|
768
806
|
You'll need to configure a directory (also known as a container), username and API key in the initializer.
|
769
|
-
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.
|
770
808
|
|
771
809
|
Using a US-based account:
|
772
810
|
|
@@ -825,14 +863,13 @@ gem "fog-google"
|
|
825
863
|
```
|
826
864
|
|
827
865
|
You'll need to configure a directory (also known as a bucket) and the credentials in the initializer.
|
828
|
-
For the sake of performance it is assumed that the directory already exists, so please create it if
|
866
|
+
For the sake of performance it is assumed that the directory already exists, so please create it if needs to be.
|
829
867
|
|
830
868
|
Please read the [fog-google README](https://github.com/fog/fog-google/blob/master/README.md) on how to get credentials.
|
831
869
|
|
832
870
|
For Google Storage JSON API (recommended):
|
833
871
|
```ruby
|
834
872
|
CarrierWave.configure do |config|
|
835
|
-
config.fog_provider = 'fog/google'
|
836
873
|
config.fog_credentials = {
|
837
874
|
provider: 'Google',
|
838
875
|
google_project: 'my-project',
|
@@ -846,7 +883,6 @@ end
|
|
846
883
|
For Google Storage XML API:
|
847
884
|
```ruby
|
848
885
|
CarrierWave.configure do |config|
|
849
|
-
config.fog_provider = 'fog/google'
|
850
886
|
config.fog_credentials = {
|
851
887
|
provider: 'Google',
|
852
888
|
google_storage_access_key_id: 'xxxxxx',
|
@@ -905,12 +941,48 @@ CarrierWave.configure do |config|
|
|
905
941
|
end
|
906
942
|
```
|
907
943
|
|
908
|
-
##
|
944
|
+
## Manipulating images
|
909
945
|
|
910
946
|
If you're uploading images, you'll probably want to manipulate them in some way,
|
911
|
-
you might want to create thumbnail images for example.
|
912
|
-
|
913
|
-
|
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:
|
914
986
|
|
915
987
|
```ruby
|
916
988
|
class AvatarUploader < CarrierWave::Uploader::Base
|
@@ -923,7 +995,6 @@ The RMagick module gives you a few methods, like
|
|
923
995
|
way. You can set a `process` callback, which will call that method any time a
|
924
996
|
file is uploaded.
|
925
997
|
There is a demonstration of convert here.
|
926
|
-
Convert will only work if the file has the same file extension, thus the use of the filename method.
|
927
998
|
|
928
999
|
```ruby
|
929
1000
|
class AvatarUploader < CarrierWave::Uploader::Base
|
@@ -931,40 +1002,59 @@ class AvatarUploader < CarrierWave::Uploader::Base
|
|
931
1002
|
|
932
1003
|
process resize_to_fill: [200, 200]
|
933
1004
|
process convert: 'png'
|
934
|
-
|
935
|
-
def filename
|
936
|
-
super.chomp(File.extname(super)) + '.png' if original_filename.present?
|
937
|
-
end
|
938
1005
|
end
|
939
1006
|
```
|
940
1007
|
|
941
1008
|
Check out the manipulate! method, which makes it easy for you to write your own
|
942
1009
|
manipulation methods.
|
943
1010
|
|
944
|
-
|
1011
|
+
### Using Vips
|
945
1012
|
|
946
|
-
|
947
|
-
CLI which is part of the standard ImageMagick kit. This allows you to have the power
|
948
|
-
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:
|
949
1014
|
|
950
|
-
|
1015
|
+
````bash
|
1016
|
+
$ sudo apt install libvips
|
1017
|
+
````
|
951
1018
|
|
952
|
-
|
1019
|
+
You also need to tell your uploader to use Vips:
|
953
1020
|
|
954
|
-
|
1021
|
+
````ruby
|
1022
|
+
class ImageFileUploader < CarrierWave::Uploader::Base
|
1023
|
+
include CarrierWave::Vips
|
1024
|
+
end
|
1025
|
+
````
|
955
1026
|
|
956
|
-
|
1027
|
+
### List of available processing methods:
|
957
1028
|
|
958
|
-
|
959
|
-
|
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>.
|
960
1031
|
|
961
|
-
|
962
|
-
|
963
|
-
|
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.
|
964
1038
|
|
965
|
-
|
966
|
-
|
967
|
-
|
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).
|
968
1058
|
|
969
1059
|
## Migrating from Paperclip
|
970
1060
|
|
@@ -1000,10 +1090,13 @@ errors:
|
|
1000
1090
|
extension_denylist_error: "You are not allowed to upload %{extension} files, prohibited types: %{prohibited_types}"
|
1001
1091
|
content_type_allowlist_error: "You are not allowed to upload %{content_type} files, allowed types: %{allowed_types}"
|
1002
1092
|
content_type_denylist_error: "You are not allowed to upload %{content_type} files"
|
1003
|
-
|
1004
|
-
mini_magick_processing_error: "Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: %{e}"
|
1093
|
+
processing_error: "Failed to manipulate, maybe it is not an image?"
|
1005
1094
|
min_size_error: "File size should be greater than %{min_size}"
|
1006
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"
|
1007
1100
|
```
|
1008
1101
|
|
1009
1102
|
The [`carrierwave-i18n`](https://github.com/carrierwaveuploader/carrierwave-i18n)
|
@@ -1066,6 +1159,31 @@ class User
|
|
1066
1159
|
end
|
1067
1160
|
```
|
1068
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
|
+
|
1069
1187
|
## Contributing to CarrierWave
|
1070
1188
|
|
1071
1189
|
See [CONTRIBUTING.md](https://github.com/carrierwaveuploader/carrierwave/blob/master/CONTRIBUTING.md)
|
@@ -1074,7 +1192,7 @@ See [CONTRIBUTING.md](https://github.com/carrierwaveuploader/carrierwave/blob/ma
|
|
1074
1192
|
|
1075
1193
|
The MIT License (MIT)
|
1076
1194
|
|
1077
|
-
Copyright (c) 2008
|
1195
|
+
Copyright (c) 2008 Jonas Nicklas
|
1078
1196
|
|
1079
1197
|
Permission is hereby granted, free of charge, to any person obtaining
|
1080
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 }
|
@@ -6,6 +6,8 @@ require 'carrierwave/downloader/remote_file'
|
|
6
6
|
module CarrierWave
|
7
7
|
module Downloader
|
8
8
|
class Base
|
9
|
+
include CarrierWave::Utilities::Uri
|
10
|
+
|
9
11
|
attr_reader :uploader
|
10
12
|
|
11
13
|
def initialize(uploader)
|
@@ -21,6 +23,7 @@ module CarrierWave
|
|
21
23
|
# [remote_headers (Hash)] Request headers
|
22
24
|
#
|
23
25
|
def download(url, remote_headers = {})
|
26
|
+
@current_download_retry_count = 0
|
24
27
|
headers = remote_headers.
|
25
28
|
reverse_merge('User-Agent' => "CarrierWave/#{CarrierWave::VERSION}")
|
26
29
|
uri = process_uri(url.to_s)
|
@@ -29,14 +32,26 @@ module CarrierWave
|
|
29
32
|
response = OpenURI.open_uri(process_uri(url.to_s), headers)
|
30
33
|
else
|
31
34
|
request = nil
|
32
|
-
|
33
|
-
|
35
|
+
if ::SsrfFilter::VERSION.to_f < 1.1
|
36
|
+
response = SsrfFilter.get(uri, headers: headers) do |req|
|
37
|
+
request = req
|
38
|
+
end
|
39
|
+
else
|
40
|
+
response = SsrfFilter.get(uri, headers: headers, request_proc: ->(req) { request = req }) do |res|
|
41
|
+
res.body # ensure to read body
|
42
|
+
end
|
34
43
|
end
|
35
44
|
response.uri = request.uri
|
36
45
|
response.value
|
37
46
|
end
|
38
47
|
rescue StandardError => e
|
39
|
-
|
48
|
+
if @current_download_retry_count < @uploader.download_retry_count
|
49
|
+
@current_download_retry_count += 1
|
50
|
+
sleep @uploader.download_retry_wait_time
|
51
|
+
retry
|
52
|
+
else
|
53
|
+
raise CarrierWave::DownloadError, "could not download file: #{e.message}"
|
54
|
+
end
|
40
55
|
end
|
41
56
|
CarrierWave::Downloader::RemoteFile.new(response)
|
42
57
|
end
|
@@ -48,17 +63,16 @@ module CarrierWave
|
|
48
63
|
#
|
49
64
|
# [url (String)] The URL where the remote file is stored
|
50
65
|
#
|
51
|
-
def process_uri(
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
66
|
+
def process_uri(source)
|
67
|
+
uri = Addressable::URI.parse(source)
|
68
|
+
uri.host = uri.normalized_host
|
69
|
+
# Perform decode first, as the path is likely to be already encoded
|
70
|
+
uri.path = encode_path(decode_uri(uri.path)) if uri.path =~ CarrierWave::Utilities::Uri::PATH_UNSAFE
|
71
|
+
uri.query = encode_non_ascii(uri.query) if uri.query
|
72
|
+
uri.fragment = encode_non_ascii(uri.fragment) if uri.fragment
|
73
|
+
URI.parse(uri.to_s)
|
60
74
|
rescue URI::InvalidURIError, Addressable::URI::InvalidURIError
|
61
|
-
raise CarrierWave::DownloadError, "couldn't parse URL: #{
|
75
|
+
raise CarrierWave::DownloadError, "couldn't parse URL: #{source}"
|
62
76
|
end
|
63
77
|
|
64
78
|
##
|
@@ -80,7 +94,7 @@ module CarrierWave
|
|
80
94
|
# my_uploader.downloader = CarrierWave::Downloader::CustomDownloader
|
81
95
|
#
|
82
96
|
def skip_ssrf_protection?(uri)
|
83
|
-
|
97
|
+
@uploader.skip_ssrf_protection
|
84
98
|
end
|
85
99
|
end
|
86
100
|
end
|
@@ -8,7 +8,10 @@ module CarrierWave
|
|
8
8
|
when String
|
9
9
|
@file = StringIO.new(file)
|
10
10
|
when Net::HTTPResponse
|
11
|
-
|
11
|
+
body = file.body
|
12
|
+
raise CarrierWave::DownloadError, 'could not download file: No Content' if body.nil?
|
13
|
+
|
14
|
+
@file = StringIO.new(body)
|
12
15
|
@content_type = file.content_type
|
13
16
|
@headers = file
|
14
17
|
@uri = file.uri
|
@@ -30,18 +33,15 @@ module CarrierWave
|
|
30
33
|
|
31
34
|
def original_filename
|
32
35
|
filename = filename_from_header || filename_from_uri
|
33
|
-
|
34
|
-
unless File.extname(filename).present? ||
|
35
|
-
|
36
|
+
extensions = Marcel::Magic.new(content_type).extensions
|
37
|
+
unless File.extname(filename).present? || extensions.blank?
|
38
|
+
extension = extensions.first
|
39
|
+
filename = "#{filename}.#{extension}"
|
36
40
|
end
|
37
41
|
filename
|
38
42
|
end
|
39
43
|
|
40
|
-
|
41
|
-
super || file.respond_to?(*args)
|
42
|
-
end
|
43
|
-
|
44
|
-
private
|
44
|
+
private
|
45
45
|
|
46
46
|
def filename_from_header
|
47
47
|
return nil unless headers['content-disposition']
|
@@ -59,7 +59,10 @@ module CarrierWave
|
|
59
59
|
def method_missing(*args, &block)
|
60
60
|
file.send(*args, &block)
|
61
61
|
end
|
62
|
+
|
63
|
+
def respond_to_missing?(*args)
|
64
|
+
super || file.respond_to?(*args)
|
65
|
+
end
|
62
66
|
end
|
63
67
|
end
|
64
68
|
end
|
65
|
-
|
@@ -8,8 +8,10 @@ en:
|
|
8
8
|
extension_denylist_error: "You are not allowed to upload %{extension} files, prohibited types: %{prohibited_types}"
|
9
9
|
content_type_allowlist_error: "You are not allowed to upload %{content_type} files, allowed types: %{allowed_types}"
|
10
10
|
content_type_denylist_error: "You are not allowed to upload %{content_type} files"
|
11
|
-
|
12
|
-
mini_magick_processing_error: "Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: %{e}"
|
13
|
-
vips_processing_error: "Failed to manipulate with vips, maybe it is not an image? Original Error: %{e}"
|
11
|
+
processing_error: "Failed to manipulate, maybe it is not an image?"
|
14
12
|
min_size_error: "File size should be greater than %{min_size}"
|
15
13
|
max_size_error: "File size should be less than %{max_size}"
|
14
|
+
min_width_error: "Image width should be greater than %{min_width}px"
|
15
|
+
max_width_error: "Image width should be less than %{max_width}px"
|
16
|
+
min_height_error: "Image height should be greater than %{min_height}px"
|
17
|
+
max_height_error: "Image height should be less than %{max_height}px"
|