carrierwave 0.11.2 → 3.1.2
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 +5 -5
- data/README.md +495 -173
- data/lib/carrierwave/compatibility/paperclip.rb +4 -4
- data/lib/carrierwave/downloader/base.rb +101 -0
- data/lib/carrierwave/downloader/remote_file.rb +68 -0
- data/lib/carrierwave/error.rb +1 -0
- data/lib/carrierwave/locale/en.yml +11 -5
- data/lib/carrierwave/mount.rb +217 -182
- data/lib/carrierwave/mounter.rb +257 -0
- data/lib/carrierwave/orm/activerecord.rb +29 -35
- data/lib/carrierwave/processing/mini_magick.rb +169 -84
- data/lib/carrierwave/processing/rmagick.rb +107 -25
- data/lib/carrierwave/processing/vips.rb +315 -0
- data/lib/carrierwave/processing.rb +1 -1
- data/lib/carrierwave/sanitized_file.rb +105 -87
- data/lib/carrierwave/storage/abstract.rb +16 -3
- data/lib/carrierwave/storage/file.rb +71 -3
- data/lib/carrierwave/storage/fog.rb +228 -57
- data/lib/carrierwave/storage.rb +1 -9
- data/lib/carrierwave/test/matchers.rb +88 -19
- data/lib/carrierwave/uploader/cache.rb +75 -45
- data/lib/carrierwave/uploader/callbacks.rb +1 -3
- data/lib/carrierwave/uploader/configuration.rb +84 -16
- data/lib/carrierwave/uploader/content_type_allowlist.rb +62 -0
- data/lib/carrierwave/uploader/content_type_denylist.rb +62 -0
- data/lib/carrierwave/uploader/default_url.rb +3 -5
- data/lib/carrierwave/uploader/dimension.rb +66 -0
- data/lib/carrierwave/uploader/download.rb +4 -74
- 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 +43 -0
- data/lib/carrierwave/uploader/mountable.rb +13 -8
- data/lib/carrierwave/uploader/processing.rb +51 -13
- data/lib/carrierwave/uploader/proxy.rb +20 -9
- data/lib/carrierwave/uploader/remove.rb +0 -2
- data/lib/carrierwave/uploader/serialization.rb +2 -4
- data/lib/carrierwave/uploader/store.rb +85 -28
- data/lib/carrierwave/uploader/url.rb +8 -7
- data/lib/carrierwave/uploader/versions.rb +175 -125
- data/lib/carrierwave/uploader.rb +12 -10
- data/lib/carrierwave/utilities/file_name.rb +47 -0
- data/lib/carrierwave/utilities/uri.rb +14 -12
- data/lib/carrierwave/utilities.rb +1 -3
- data/lib/carrierwave/validations/active_model.rb +7 -11
- data/lib/carrierwave/version.rb +1 -1
- data/lib/carrierwave.rb +48 -21
- data/lib/generators/templates/{uploader.rb → uploader.rb.erb} +8 -11
- data/lib/generators/uploader_generator.rb +3 -3
- metadata +124 -86
- data/lib/carrierwave/locale/cs.yml +0 -11
- data/lib/carrierwave/locale/de.yml +0 -11
- data/lib/carrierwave/locale/el.yml +0 -11
- data/lib/carrierwave/locale/es.yml +0 -11
- data/lib/carrierwave/locale/fr.yml +0 -11
- data/lib/carrierwave/locale/ja.yml +0 -11
- data/lib/carrierwave/locale/nb.yml +0 -11
- data/lib/carrierwave/locale/nl.yml +0 -11
- data/lib/carrierwave/locale/pl.yml +0 -11
- data/lib/carrierwave/locale/pt-BR.yml +0 -11
- data/lib/carrierwave/locale/pt-PT.yml +0 -11
- data/lib/carrierwave/locale/ru.yml +0 -11
- data/lib/carrierwave/locale/sk.yml +0 -11
- data/lib/carrierwave/locale/tr.yml +0 -11
- data/lib/carrierwave/processing/mime_types.rb +0 -74
- 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 -47
- data/lib/carrierwave/uploader/extension_whitelist.rb +0 -49
- data/lib/carrierwave/utilities/deprecation.rb +0 -18
data/README.md
CHANGED
|
@@ -3,36 +3,46 @@
|
|
|
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
|
+
[](https://codeclimate.com/github/carrierwaveuploader/carrierwave)
|
|
8
|
+
[](https://dependabot.com/compatibility-score.html?dependency-name=carrierwave&package-manager=bundler&version-scheme=semver)
|
|
9
|
+
|
|
8
10
|
|
|
9
11
|
## Information
|
|
10
12
|
|
|
11
|
-
* RDoc documentation [available on RubyDoc.info](
|
|
13
|
+
* RDoc documentation [available on RubyDoc.info](https://rubydoc.info/gems/carrierwave)
|
|
12
14
|
* Source code [available on GitHub](http://github.com/carrierwaveuploader/carrierwave)
|
|
13
15
|
* More information, known limitations, and how-tos [available on the wiki](https://github.com/carrierwaveuploader/carrierwave/wiki)
|
|
14
16
|
|
|
15
17
|
## Getting Help
|
|
16
18
|
|
|
17
|
-
* Please ask the [
|
|
19
|
+
* Please ask the community on [Stack Overflow](https://stackoverflow.com/questions/tagged/carrierwave) for help if you have any questions. Please do not post usage questions on the issue tracker.
|
|
18
20
|
* Please report bugs on the [issue tracker](http://github.com/carrierwaveuploader/carrierwave/issues) but read the "getting help" section in the wiki first.
|
|
19
21
|
|
|
20
22
|
## Installation
|
|
21
23
|
|
|
22
|
-
Install the latest
|
|
24
|
+
Install the latest release:
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
```
|
|
27
|
+
$ gem install carrierwave
|
|
28
|
+
```
|
|
25
29
|
|
|
26
30
|
In Rails, add it to your Gemfile:
|
|
27
31
|
|
|
28
32
|
```ruby
|
|
29
|
-
gem 'carrierwave'
|
|
33
|
+
gem 'carrierwave', '~> 3.0'
|
|
30
34
|
```
|
|
31
35
|
|
|
32
36
|
Finally, restart the server to apply the changes.
|
|
33
37
|
|
|
34
|
-
|
|
35
|
-
|
|
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.
|
|
36
46
|
|
|
37
47
|
## Getting Started
|
|
38
48
|
|
|
@@ -85,12 +95,12 @@ a migration:
|
|
|
85
95
|
|
|
86
96
|
|
|
87
97
|
rails g migration add_avatar_to_users avatar:string
|
|
88
|
-
|
|
98
|
+
rails db:migrate
|
|
89
99
|
|
|
90
100
|
Open your model file and mount the uploader:
|
|
91
101
|
|
|
92
102
|
```ruby
|
|
93
|
-
class User <
|
|
103
|
+
class User < ApplicationRecord
|
|
94
104
|
mount_uploader :avatar, AvatarUploader
|
|
95
105
|
end
|
|
96
106
|
```
|
|
@@ -100,24 +110,103 @@ automatically be stored when the record is saved.
|
|
|
100
110
|
|
|
101
111
|
```ruby
|
|
102
112
|
u = User.new
|
|
103
|
-
u.avatar = params[:file]
|
|
104
|
-
|
|
113
|
+
u.avatar = params[:file] # Assign a file like this, or
|
|
114
|
+
|
|
115
|
+
# like this
|
|
116
|
+
File.open('somewhere') do |f|
|
|
117
|
+
u.avatar = f
|
|
118
|
+
end
|
|
119
|
+
|
|
105
120
|
u.save!
|
|
106
121
|
u.avatar.url # => '/url/to/file.png'
|
|
107
122
|
u.avatar.current_path # => 'path/to/file.png'
|
|
108
|
-
u.
|
|
123
|
+
u.avatar_identifier # => 'file.png'
|
|
109
124
|
```
|
|
110
125
|
|
|
126
|
+
**Note**: `u.avatar` will never return nil, even if there is no photo associated to it.
|
|
127
|
+
To check if a photo was saved to the model, use `u.avatar.file.nil?` instead.
|
|
128
|
+
|
|
111
129
|
### DataMapper, Mongoid, Sequel
|
|
112
130
|
|
|
113
131
|
Other ORM support has been extracted into separate gems:
|
|
114
132
|
|
|
115
133
|
* [carrierwave-datamapper](https://github.com/carrierwaveuploader/carrierwave-datamapper)
|
|
116
134
|
* [carrierwave-mongoid](https://github.com/carrierwaveuploader/carrierwave-mongoid)
|
|
117
|
-
* [carrierwave-sequel](https://github.com/
|
|
135
|
+
* [carrierwave-sequel](https://github.com/carrierwaveuploader/carrierwave-sequel)
|
|
118
136
|
|
|
119
137
|
There are more extensions listed in [the wiki](https://github.com/carrierwaveuploader/carrierwave/wiki)
|
|
120
138
|
|
|
139
|
+
## Multiple file uploads
|
|
140
|
+
|
|
141
|
+
CarrierWave also has convenient support for multiple file upload fields.
|
|
142
|
+
|
|
143
|
+
### ActiveRecord
|
|
144
|
+
|
|
145
|
+
Add a column which can store an array. This could be an array column or a JSON
|
|
146
|
+
column for example. Your choice depends on what your database supports. For
|
|
147
|
+
example, create a migration like this:
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
#### For databases with ActiveRecord json data type support (e.g. PostgreSQL, MySQL)
|
|
151
|
+
|
|
152
|
+
rails g migration add_avatars_to_users avatars:json
|
|
153
|
+
rails db:migrate
|
|
154
|
+
|
|
155
|
+
#### For database without ActiveRecord json data type support (e.g. SQLite)
|
|
156
|
+
|
|
157
|
+
rails g migration add_avatars_to_users avatars:string
|
|
158
|
+
rails db:migrate
|
|
159
|
+
|
|
160
|
+
__Note__: JSON datatype doesn't exists in SQLite adapter, that's why you can use a string datatype which will be serialized in model.
|
|
161
|
+
|
|
162
|
+
Open your model file and mount the uploader:
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
```ruby
|
|
166
|
+
class User < ApplicationRecord
|
|
167
|
+
mount_uploaders :avatars, AvatarUploader
|
|
168
|
+
serialize :avatars, JSON # If you use SQLite, add this line.
|
|
169
|
+
end
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Make sure that you mount the uploader with write (mount_uploaders) with `s` not (mount_uploader)
|
|
173
|
+
in order to avoid errors when uploading multiple files
|
|
174
|
+
|
|
175
|
+
Make sure your file input fields are set up as multiple file fields. For
|
|
176
|
+
example in Rails you'll want to do something like this:
|
|
177
|
+
|
|
178
|
+
```erb
|
|
179
|
+
<%= form.file_field :avatars, multiple: true %>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Also, make sure your upload controller permits the multiple file upload attribute, *pointing to an empty array in a hash*. For example:
|
|
183
|
+
|
|
184
|
+
```ruby
|
|
185
|
+
params.require(:user).permit(:email, :first_name, :last_name, {avatars: []})
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Now you can select multiple files in the upload dialog (e.g. SHIFT+SELECT), and they will
|
|
189
|
+
automatically be stored when the record is saved.
|
|
190
|
+
|
|
191
|
+
```ruby
|
|
192
|
+
u = User.new(params[:user])
|
|
193
|
+
u.save!
|
|
194
|
+
u.avatars[0].url # => '/url/to/file.png'
|
|
195
|
+
u.avatars[0].current_path # => 'path/to/file.png'
|
|
196
|
+
u.avatars[0].identifier # => 'file.png'
|
|
197
|
+
```
|
|
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
|
+
|
|
121
210
|
## Changing the storage directory
|
|
122
211
|
|
|
123
212
|
In order to change where uploaded files are put, just override the `store_dir`
|
|
@@ -144,124 +233,153 @@ class MyUploader < CarrierWave::Uploader::Base
|
|
|
144
233
|
end
|
|
145
234
|
```
|
|
146
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
|
+
|
|
147
250
|
## Securing uploads
|
|
148
251
|
|
|
149
|
-
Certain
|
|
150
|
-
files or other script files. CarrierWave allows you to specify
|
|
151
|
-
allowed extensions.
|
|
252
|
+
Certain files might be dangerous if uploaded to the wrong location, such as PHP
|
|
253
|
+
files or other script files. CarrierWave allows you to specify an allowlist of
|
|
254
|
+
allowed extensions or content types.
|
|
152
255
|
|
|
153
256
|
If you're mounting the uploader, uploading a file with the wrong extension will
|
|
154
257
|
make the record invalid instead. Otherwise, an error is raised.
|
|
155
258
|
|
|
156
259
|
```ruby
|
|
157
260
|
class MyUploader < CarrierWave::Uploader::Base
|
|
158
|
-
def
|
|
261
|
+
def extension_allowlist
|
|
159
262
|
%w(jpg jpeg gif png)
|
|
160
263
|
end
|
|
161
264
|
end
|
|
162
265
|
```
|
|
163
266
|
|
|
267
|
+
The same thing could be done using content types.
|
|
268
|
+
Let's say we need an uploader that accepts only images. This can be done like this
|
|
269
|
+
|
|
270
|
+
```ruby
|
|
271
|
+
class MyUploader < CarrierWave::Uploader::Base
|
|
272
|
+
def content_type_allowlist
|
|
273
|
+
/image\//
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
You can use a denylist to reject content types.
|
|
279
|
+
Let's say we need an uploader that reject JSON files. This can be done like this
|
|
280
|
+
|
|
281
|
+
```ruby
|
|
282
|
+
class NoJsonUploader < CarrierWave::Uploader::Base
|
|
283
|
+
def content_type_denylist
|
|
284
|
+
['application/text', 'application/json']
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
```
|
|
288
|
+
|
|
164
289
|
### CVE-2016-3714 (ImageTragick)
|
|
165
|
-
This version of CarrierWave has the ability to mitigate CVE-2016-3714. However, you **MUST** set a
|
|
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.
|
|
166
291
|
|
|
167
|
-
|
|
292
|
+
|
|
293
|
+
A valid allowlist that will restrict your uploader to images only, and mitigate the CVE is:
|
|
168
294
|
|
|
169
295
|
```ruby
|
|
170
296
|
class MyUploader < CarrierWave::Uploader::Base
|
|
171
|
-
def
|
|
297
|
+
def content_type_allowlist
|
|
172
298
|
[/image\//]
|
|
173
299
|
end
|
|
174
300
|
end
|
|
175
301
|
```
|
|
176
302
|
|
|
177
|
-
**WARNING**: A `
|
|
178
|
-
|
|
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.
|
|
179
304
|
|
|
180
305
|
### Filenames and unicode chars
|
|
181
306
|
|
|
182
307
|
Another security issue you should care for is the file names (see
|
|
183
308
|
[Ruby On Rails Security Guide](http://guides.rubyonrails.org/security.html#file-uploads)).
|
|
184
|
-
By default, CarrierWave provides only English letters, arabic numerals and
|
|
185
|
-
|
|
309
|
+
By default, CarrierWave provides only English letters, arabic numerals and some symbols as
|
|
310
|
+
allowlisted characters in the file name. If you want to support local scripts (Cyrillic letters, letters with diacritics and so on), you
|
|
186
311
|
have to override `sanitize_regexp` method. It should return regular expression which would match
|
|
187
312
|
all *non*-allowed symbols.
|
|
188
313
|
|
|
189
|
-
With Ruby 1.9 and higher you can simply write (as it has [Oniguruma](http://oniguruma.rubyforge.org/oniguruma/)
|
|
190
|
-
built-in):
|
|
191
|
-
|
|
192
314
|
```ruby
|
|
193
315
|
CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/
|
|
194
316
|
```
|
|
195
317
|
|
|
196
|
-
With Ruby 1.8 you have to manually specify all character ranges. For example, for files which may
|
|
197
|
-
contain Russian letters:
|
|
198
|
-
|
|
199
|
-
```ruby
|
|
200
|
-
CarrierWave::SanitizedFile.sanitize_regexp = /[^a-zA-Zа-яА-ЯёЁ0-9\.\-\+_]/u
|
|
201
|
-
```
|
|
202
|
-
|
|
203
318
|
Also make sure that allowing non-latin characters won't cause a compatibility issue with a third-party
|
|
204
319
|
plugins or client-side software.
|
|
205
320
|
|
|
206
321
|
## Setting the content type
|
|
207
322
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
This adds a dependency on the [mime-types](http://rubygems.org/gems/mime-types) gem,
|
|
211
|
-
but is recommended when using fog, and fog already has a dependency on mime-types.
|
|
212
|
-
|
|
213
|
-
```ruby
|
|
214
|
-
require 'carrierwave/processing/mime_types'
|
|
215
|
-
|
|
216
|
-
class MyUploader < CarrierWave::Uploader::Base
|
|
217
|
-
include CarrierWave::MimeTypes
|
|
218
|
-
|
|
219
|
-
process :set_content_type
|
|
220
|
-
end
|
|
221
|
-
```
|
|
323
|
+
As of v0.11.0, the `mime-types` gem is a runtime dependency and the content type is set automatically.
|
|
324
|
+
You no longer need to do this manually.
|
|
222
325
|
|
|
223
326
|
## Adding versions
|
|
224
327
|
|
|
225
|
-
Often you'll want to add different versions of the same file. The classic example is image thumbnails
|
|
226
|
-
|
|
227
|
-
*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.
|
|
228
|
-
|
|
229
|
-
Some documentation refers to RMagick instead of MiniMagick but MiniMagick is recommended.
|
|
230
|
-
|
|
231
|
-
To install Imagemagick on OSX with homebrew type the following:
|
|
232
|
-
|
|
233
|
-
```
|
|
234
|
-
$ brew install imagemagick
|
|
235
|
-
```
|
|
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).
|
|
236
330
|
|
|
237
331
|
```ruby
|
|
238
332
|
class MyUploader < CarrierWave::Uploader::Base
|
|
239
333
|
include CarrierWave::MiniMagick
|
|
240
334
|
|
|
241
|
-
process :
|
|
335
|
+
process resize_to_fit: [800, 800]
|
|
242
336
|
|
|
243
337
|
version :thumb do
|
|
244
|
-
process :
|
|
338
|
+
process resize_to_fill: [200,200]
|
|
245
339
|
end
|
|
246
340
|
|
|
247
341
|
end
|
|
248
342
|
```
|
|
249
343
|
|
|
250
344
|
When this uploader is used, an uploaded image would be scaled to be no larger
|
|
251
|
-
than 800 by 800 pixels.
|
|
252
|
-
|
|
345
|
+
than 800 by 800 pixels. The original aspect ratio will be kept.
|
|
346
|
+
|
|
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
|
|
349
|
+
that the width and height specified are filled, only cropping
|
|
350
|
+
if the aspect ratio requires it.
|
|
351
|
+
|
|
352
|
+
The above uploader could be used like this:
|
|
253
353
|
|
|
254
354
|
```ruby
|
|
255
355
|
uploader = AvatarUploader.new
|
|
256
356
|
uploader.store!(my_file) # size: 1024x768
|
|
257
357
|
|
|
258
|
-
uploader.url # => '/url/to/my_file.png' # size:
|
|
358
|
+
uploader.url # => '/url/to/my_file.png' # size: 800x800
|
|
259
359
|
uploader.thumb.url # => '/url/to/thumb_my_file.png' # size: 200x200
|
|
260
360
|
```
|
|
261
361
|
|
|
262
362
|
One important thing to remember is that process is called *before* versions are
|
|
263
363
|
created. This can cut down on processing cost.
|
|
264
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
|
+
|
|
265
383
|
It is possible to nest versions within versions:
|
|
266
384
|
|
|
267
385
|
```ruby
|
|
@@ -283,11 +401,11 @@ properties within the model or based on the picture itself.
|
|
|
283
401
|
```ruby
|
|
284
402
|
class MyUploader < CarrierWave::Uploader::Base
|
|
285
403
|
|
|
286
|
-
version :human, :
|
|
287
|
-
version :monkey, :
|
|
288
|
-
version :banner, :
|
|
404
|
+
version :human, if: :is_human?
|
|
405
|
+
version :monkey, if: :is_monkey?
|
|
406
|
+
version :banner, if: :is_landscape?
|
|
289
407
|
|
|
290
|
-
|
|
408
|
+
private
|
|
291
409
|
|
|
292
410
|
def is_human? picture
|
|
293
411
|
model.can_program?(:ruby)
|
|
@@ -298,7 +416,7 @@ protected
|
|
|
298
416
|
end
|
|
299
417
|
|
|
300
418
|
def is_landscape? picture
|
|
301
|
-
image = MiniMagick::Image.
|
|
419
|
+
image = MiniMagick::Image.new(picture.path)
|
|
302
420
|
image[:width] > image[:height]
|
|
303
421
|
end
|
|
304
422
|
|
|
@@ -321,15 +439,34 @@ class MyUploader < CarrierWave::Uploader::Base
|
|
|
321
439
|
process resize_to_fill: [280, 280]
|
|
322
440
|
end
|
|
323
441
|
|
|
324
|
-
version :small_thumb, :
|
|
442
|
+
version :small_thumb, from_version: :thumb do
|
|
325
443
|
process resize_to_fill: [20, 20]
|
|
326
444
|
end
|
|
327
445
|
|
|
328
446
|
end
|
|
329
447
|
```
|
|
330
448
|
|
|
331
|
-
|
|
332
|
-
|
|
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.
|
|
333
470
|
|
|
334
471
|
## Making uploads work across form redisplays
|
|
335
472
|
|
|
@@ -340,7 +477,7 @@ file, just add a hidden field called `avatar_cache` (don't forget to add it to
|
|
|
340
477
|
the attr_accessible list as necessary). In Rails, this would look like this:
|
|
341
478
|
|
|
342
479
|
```erb
|
|
343
|
-
<%= form_for @user, :
|
|
480
|
+
<%= form_for @user, html: { multipart: true } do |f| %>
|
|
344
481
|
<p>
|
|
345
482
|
<label>My Avatar</label>
|
|
346
483
|
<%= f.file_field :avatar %>
|
|
@@ -353,7 +490,7 @@ It might be a good idea to show the user that a file has been uploaded, in the
|
|
|
353
490
|
case of images, a small thumbnail would be a good indicator:
|
|
354
491
|
|
|
355
492
|
```erb
|
|
356
|
-
<%= form_for @user, :
|
|
493
|
+
<%= form_for @user, html: { multipart: true } do |f| %>
|
|
357
494
|
<p>
|
|
358
495
|
<label>My Avatar</label>
|
|
359
496
|
<%= image_tag(@user.avatar_url) if @user.avatar? %>
|
|
@@ -369,7 +506,7 @@ If you want to remove a previously uploaded file on a mounted uploader, you can
|
|
|
369
506
|
easily add a checkbox to the form which will remove the file when checked.
|
|
370
507
|
|
|
371
508
|
```erb
|
|
372
|
-
<%= form_for @user, :
|
|
509
|
+
<%= form_for @user, html: { multipart: true } do |f| %>
|
|
373
510
|
<p>
|
|
374
511
|
<label>My Avatar</label>
|
|
375
512
|
<%= image_tag(@user.avatar_url) if @user.avatar? %>
|
|
@@ -400,7 +537,7 @@ via a URL. CarrierWave makes this simple, just add the appropriate attribute to
|
|
|
400
537
|
form and you're good to go:
|
|
401
538
|
|
|
402
539
|
```erb
|
|
403
|
-
<%= form_for @user, :
|
|
540
|
+
<%= form_for @user, html: { multipart: true } do |f| %>
|
|
404
541
|
<p>
|
|
405
542
|
<label>My Avatar URL:</label>
|
|
406
543
|
<%= image_tag(@user.avatar_url) if @user.avatar? %>
|
|
@@ -414,6 +551,17 @@ failures automatically with attribute validation errors. If you aren't, or you
|
|
|
414
551
|
disable CarrierWave's `validate_download` option, you'll need to handle those
|
|
415
552
|
errors yourself.
|
|
416
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
|
+
|
|
417
565
|
## Providing a default URL
|
|
418
566
|
|
|
419
567
|
In many cases, especially when working with images, it might be a good idea to
|
|
@@ -422,7 +570,7 @@ this easily by overriding the `default_url` method in your uploader:
|
|
|
422
570
|
|
|
423
571
|
```ruby
|
|
424
572
|
class MyUploader < CarrierWave::Uploader::Base
|
|
425
|
-
def default_url
|
|
573
|
+
def default_url(*args)
|
|
426
574
|
"/images/fallback/" + [version_name, "default.png"].compact.join('_')
|
|
427
575
|
end
|
|
428
576
|
end
|
|
@@ -432,7 +580,7 @@ Or if you are using the Rails asset pipeline:
|
|
|
432
580
|
|
|
433
581
|
```ruby
|
|
434
582
|
class MyUploader < CarrierWave::Uploader::Base
|
|
435
|
-
def default_url
|
|
583
|
+
def default_url(*args)
|
|
436
584
|
ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
|
|
437
585
|
end
|
|
438
586
|
end
|
|
@@ -459,7 +607,7 @@ instance.recreate_versions!(:thumb, :large)
|
|
|
459
607
|
Or on a mounted uploader:
|
|
460
608
|
|
|
461
609
|
```ruby
|
|
462
|
-
User.
|
|
610
|
+
User.find_each do |user|
|
|
463
611
|
user.avatar.recreate_versions!
|
|
464
612
|
end
|
|
465
613
|
```
|
|
@@ -467,7 +615,7 @@ end
|
|
|
467
615
|
Note: `recreate_versions!` will throw an exception on records without an image. To avoid this, scope the records to those with images or check if an image exists within the block. If you're using ActiveRecord, recreating versions for a user avatar might look like this:
|
|
468
616
|
|
|
469
617
|
```ruby
|
|
470
|
-
User.
|
|
618
|
+
User.find_each do |user|
|
|
471
619
|
user.avatar.recreate_versions! if user.avatar?
|
|
472
620
|
end
|
|
473
621
|
```
|
|
@@ -497,18 +645,31 @@ If you're using Rails, create an initializer for this:
|
|
|
497
645
|
|
|
498
646
|
config/initializers/carrierwave.rb
|
|
499
647
|
|
|
648
|
+
If you want CarrierWave to fail noisily in development, you can change these configs in your environment file:
|
|
649
|
+
|
|
650
|
+
```ruby
|
|
651
|
+
CarrierWave.configure do |config|
|
|
652
|
+
config.ignore_integrity_errors = false
|
|
653
|
+
config.ignore_processing_errors = false
|
|
654
|
+
config.ignore_download_errors = false
|
|
655
|
+
end
|
|
656
|
+
```
|
|
657
|
+
|
|
500
658
|
|
|
501
659
|
## Testing with CarrierWave
|
|
502
660
|
|
|
503
661
|
It's a good idea to test your uploaders in isolation. In order to speed up your
|
|
504
|
-
tests, it's recommended to switch off processing in your tests, and to use the
|
|
505
|
-
|
|
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:
|
|
506
666
|
|
|
507
667
|
```ruby
|
|
508
668
|
if Rails.env.test? or Rails.env.cucumber?
|
|
509
669
|
CarrierWave.configure do |config|
|
|
510
670
|
config.storage = :file
|
|
511
671
|
config.enable_processing = false
|
|
672
|
+
config.skip_ssrf_protection = true
|
|
512
673
|
end
|
|
513
674
|
end
|
|
514
675
|
```
|
|
@@ -527,35 +688,43 @@ require 'carrierwave/test/matchers'
|
|
|
527
688
|
describe MyUploader do
|
|
528
689
|
include CarrierWave::Test::Matchers
|
|
529
690
|
|
|
691
|
+
let(:user) { double('user') }
|
|
692
|
+
let(:uploader) { MyUploader.new(user, :avatar) }
|
|
693
|
+
|
|
530
694
|
before do
|
|
531
695
|
MyUploader.enable_processing = true
|
|
532
|
-
|
|
533
|
-
@uploader.store!(File.open(path_to_file))
|
|
696
|
+
File.open(path_to_file) { |f| uploader.store!(f) }
|
|
534
697
|
end
|
|
535
698
|
|
|
536
699
|
after do
|
|
537
700
|
MyUploader.enable_processing = false
|
|
538
|
-
|
|
701
|
+
uploader.remove!
|
|
539
702
|
end
|
|
540
703
|
|
|
541
704
|
context 'the thumb version' do
|
|
542
|
-
it "
|
|
543
|
-
|
|
705
|
+
it "scales down a landscape image to be exactly 64 by 64 pixels" do
|
|
706
|
+
expect(uploader.thumb).to have_dimensions(64, 64)
|
|
544
707
|
end
|
|
545
708
|
end
|
|
546
709
|
|
|
547
710
|
context 'the small version' do
|
|
548
|
-
it "
|
|
549
|
-
|
|
711
|
+
it "scales down a landscape image to fit within 200 by 200 pixels" do
|
|
712
|
+
expect(uploader.small).to be_no_larger_than(200, 200)
|
|
550
713
|
end
|
|
551
714
|
end
|
|
552
715
|
|
|
553
|
-
it "
|
|
554
|
-
|
|
716
|
+
it "makes the image readable only to the owner and not executable" do
|
|
717
|
+
expect(uploader).to have_permissions(0600)
|
|
718
|
+
end
|
|
719
|
+
|
|
720
|
+
it "has the correct format" do
|
|
721
|
+
expect(uploader).to be_format('png')
|
|
555
722
|
end
|
|
556
723
|
end
|
|
557
724
|
```
|
|
558
725
|
|
|
726
|
+
If you're looking for minitest asserts, checkout [carrierwave_asserts](https://github.com/hcfairbanks/carrierwave_asserts).
|
|
727
|
+
|
|
559
728
|
Setting the enable_processing flag on an uploader will prevent any of the versions from processing as well.
|
|
560
729
|
Processing can be enabled for a single version by setting the processing flag on the version like so:
|
|
561
730
|
|
|
@@ -563,31 +732,48 @@ Processing can be enabled for a single version by setting the processing flag on
|
|
|
563
732
|
@uploader.thumb.enable_processing = true
|
|
564
733
|
```
|
|
565
734
|
|
|
735
|
+
## Fog
|
|
736
|
+
|
|
737
|
+
If you want to use fog you must add in your CarrierWave initializer the
|
|
738
|
+
following lines
|
|
739
|
+
|
|
740
|
+
```ruby
|
|
741
|
+
config.fog_credentials = { ... } # Provider specific credentials
|
|
742
|
+
```
|
|
743
|
+
|
|
566
744
|
## Using Amazon S3
|
|
567
745
|
|
|
568
|
-
[Fog](http://github.com/fog/fog) is used to support Amazon S3. Ensure you have it in your Gemfile:
|
|
746
|
+
[Fog AWS](http://github.com/fog/fog-aws) is used to support Amazon S3. Ensure you have it in your Gemfile:
|
|
569
747
|
|
|
570
748
|
```ruby
|
|
571
|
-
gem "fog"
|
|
749
|
+
gem "fog-aws"
|
|
572
750
|
```
|
|
573
751
|
|
|
574
752
|
You'll need to provide your fog_credentials and a fog_directory (also known as a bucket) in an initializer.
|
|
575
|
-
For the sake of performance it is assumed that the directory already exists, so please create it if
|
|
753
|
+
For the sake of performance it is assumed that the directory already exists, so please create it if it needs to be.
|
|
576
754
|
You can also pass in additional options, as documented fully in lib/carrierwave/storage/fog.rb. Here's a full example:
|
|
577
755
|
|
|
578
756
|
```ruby
|
|
579
757
|
CarrierWave.configure do |config|
|
|
580
758
|
config.fog_credentials = {
|
|
581
|
-
:
|
|
582
|
-
:
|
|
583
|
-
:
|
|
584
|
-
:
|
|
585
|
-
:
|
|
586
|
-
:
|
|
759
|
+
provider: 'AWS', # required
|
|
760
|
+
aws_access_key_id: 'xxx', # required unless using use_iam_profile
|
|
761
|
+
aws_secret_access_key: 'yyy', # required unless using use_iam_profile
|
|
762
|
+
use_iam_profile: true, # optional, defaults to false
|
|
763
|
+
region: 'eu-west-1', # optional, defaults to 'us-east-1'
|
|
764
|
+
host: 's3.example.com', # optional, defaults to nil
|
|
765
|
+
endpoint: 'https://s3.example.com:8080' # optional, defaults to nil
|
|
587
766
|
}
|
|
588
|
-
config.fog_directory = '
|
|
589
|
-
config.fog_public = false
|
|
590
|
-
config.fog_attributes = {
|
|
767
|
+
config.fog_directory = 'name_of_bucket' # required
|
|
768
|
+
config.fog_public = false # optional, defaults to true
|
|
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
|
|
591
777
|
end
|
|
592
778
|
```
|
|
593
779
|
|
|
@@ -601,6 +787,14 @@ end
|
|
|
601
787
|
|
|
602
788
|
That's it! You can still use the `CarrierWave::Uploader#url` method to return the url to the file on Amazon S3.
|
|
603
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
|
+
|
|
604
798
|
## Using Rackspace Cloud Files
|
|
605
799
|
|
|
606
800
|
[Fog](http://github.com/fog/fog) is used to support Rackspace Cloud Files. Ensure you have it in your Gemfile:
|
|
@@ -610,17 +804,17 @@ gem "fog"
|
|
|
610
804
|
```
|
|
611
805
|
|
|
612
806
|
You'll need to configure a directory (also known as a container), username and API key in the initializer.
|
|
613
|
-
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.
|
|
614
808
|
|
|
615
809
|
Using a US-based account:
|
|
616
810
|
|
|
617
811
|
```ruby
|
|
618
812
|
CarrierWave.configure do |config|
|
|
619
813
|
config.fog_credentials = {
|
|
620
|
-
:
|
|
621
|
-
:
|
|
622
|
-
:
|
|
623
|
-
:
|
|
814
|
+
provider: 'Rackspace',
|
|
815
|
+
rackspace_username: 'xxxxxx',
|
|
816
|
+
rackspace_api_key: 'yyyyyy',
|
|
817
|
+
rackspace_region: :ord # optional, defaults to :dfw
|
|
624
818
|
}
|
|
625
819
|
config.fog_directory = 'name_of_directory'
|
|
626
820
|
end
|
|
@@ -631,11 +825,11 @@ Using a UK-based account:
|
|
|
631
825
|
```ruby
|
|
632
826
|
CarrierWave.configure do |config|
|
|
633
827
|
config.fog_credentials = {
|
|
634
|
-
:
|
|
635
|
-
:
|
|
636
|
-
:
|
|
637
|
-
:
|
|
638
|
-
:
|
|
828
|
+
provider: 'Rackspace',
|
|
829
|
+
rackspace_username: 'xxxxxx',
|
|
830
|
+
rackspace_api_key: 'yyyyyy',
|
|
831
|
+
rackspace_auth_url: Fog::Rackspace::UK_AUTH_ENDPOINT,
|
|
832
|
+
rackspace_region: :lon
|
|
639
833
|
}
|
|
640
834
|
config.fog_directory = 'name_of_directory'
|
|
641
835
|
end
|
|
@@ -660,29 +854,41 @@ end
|
|
|
660
854
|
That's it! You can still use the `CarrierWave::Uploader#url` method to return
|
|
661
855
|
the url to the file on Rackspace Cloud Files.
|
|
662
856
|
|
|
663
|
-
## Using Google Storage
|
|
857
|
+
## Using Google Cloud Storage
|
|
664
858
|
|
|
665
|
-
[Fog](http://github.com/fog/fog) 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:
|
|
666
860
|
|
|
667
861
|
```ruby
|
|
668
|
-
gem "fog"
|
|
862
|
+
gem "fog-google"
|
|
669
863
|
```
|
|
670
864
|
|
|
671
|
-
You'll need to configure a directory (also known as a bucket)
|
|
672
|
-
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.
|
|
673
867
|
|
|
674
|
-
|
|
675
|
-
under the section “Interoperable Access”.
|
|
868
|
+
Please read the [fog-google README](https://github.com/fog/fog-google/blob/master/README.md) on how to get credentials.
|
|
676
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
|
+
```
|
|
677
882
|
|
|
883
|
+
For Google Storage XML API:
|
|
678
884
|
```ruby
|
|
679
885
|
CarrierWave.configure do |config|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
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'
|
|
686
892
|
end
|
|
687
893
|
```
|
|
688
894
|
|
|
@@ -697,6 +903,31 @@ end
|
|
|
697
903
|
That's it! You can still use the `CarrierWave::Uploader#url` method to return
|
|
698
904
|
the url to the file on Google.
|
|
699
905
|
|
|
906
|
+
## Optimized Loading of Fog
|
|
907
|
+
|
|
908
|
+
Since Carrierwave doesn't know which parts of Fog you intend to use, it will just load the entire library (unless you use e.g. [`fog-aws`, `fog-google`] instead of fog proper). If you prefer to load fewer classes into your application, you need to load those parts of Fog yourself *before* loading CarrierWave in your Gemfile. Ex:
|
|
909
|
+
|
|
910
|
+
```ruby
|
|
911
|
+
gem "fog", "~> 1.27", require: "fog/rackspace/storage"
|
|
912
|
+
gem "carrierwave"
|
|
913
|
+
```
|
|
914
|
+
|
|
915
|
+
A couple of notes about versions:
|
|
916
|
+
* This functionality was introduced in Fog v1.20.
|
|
917
|
+
* This functionality is slated for CarrierWave v1.0.0.
|
|
918
|
+
|
|
919
|
+
If you're not relying on Gemfile entries alone and are requiring "carrierwave" anywhere, ensure you require "fog/rackspace/storage" before it. Ex:
|
|
920
|
+
|
|
921
|
+
```ruby
|
|
922
|
+
require "fog/rackspace/storage"
|
|
923
|
+
require "carrierwave"
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
Beware that this specific require is only needed when working with a fog provider that was not extracted to its own gem yet.
|
|
927
|
+
A list of the extracted providers can be found in the page of the `fog` organizations [here](https://github.com/fog).
|
|
928
|
+
|
|
929
|
+
When in doubt, inspect `Fog.constants` to see what has been loaded.
|
|
930
|
+
|
|
700
931
|
## Dynamic Asset Host
|
|
701
932
|
|
|
702
933
|
The `asset_host` config property can be assigned a proc (or anything that responds to `call`) for generating the host dynamically. The proc-compliant object gets an instance of the current `CarrierWave::Storage::Fog::File` or `CarrierWave::SanitizedFile` as its only argument.
|
|
@@ -710,12 +941,48 @@ CarrierWave.configure do |config|
|
|
|
710
941
|
end
|
|
711
942
|
```
|
|
712
943
|
|
|
713
|
-
##
|
|
944
|
+
## Manipulating images
|
|
714
945
|
|
|
715
946
|
If you're uploading images, you'll probably want to manipulate them in some way,
|
|
716
|
-
you might want to create thumbnail images for example.
|
|
717
|
-
|
|
718
|
-
|
|
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:
|
|
719
986
|
|
|
720
987
|
```ruby
|
|
721
988
|
class AvatarUploader < CarrierWave::Uploader::Base
|
|
@@ -728,48 +995,66 @@ The RMagick module gives you a few methods, like
|
|
|
728
995
|
way. You can set a `process` callback, which will call that method any time a
|
|
729
996
|
file is uploaded.
|
|
730
997
|
There is a demonstration of convert here.
|
|
731
|
-
Convert will only work if the file has the same file extension, thus the use of the filename method.
|
|
732
998
|
|
|
733
999
|
```ruby
|
|
734
1000
|
class AvatarUploader < CarrierWave::Uploader::Base
|
|
735
1001
|
include CarrierWave::RMagick
|
|
736
1002
|
|
|
737
|
-
process :
|
|
738
|
-
process :
|
|
739
|
-
|
|
740
|
-
def filename
|
|
741
|
-
super.chomp(File.extname(super)) + '.png' if original_filename.present?
|
|
742
|
-
end
|
|
1003
|
+
process resize_to_fill: [200, 200]
|
|
1004
|
+
process convert: 'png'
|
|
743
1005
|
end
|
|
744
1006
|
```
|
|
745
1007
|
|
|
746
1008
|
Check out the manipulate! method, which makes it easy for you to write your own
|
|
747
1009
|
manipulation methods.
|
|
748
1010
|
|
|
749
|
-
|
|
1011
|
+
### Using Vips
|
|
750
1012
|
|
|
751
|
-
|
|
752
|
-
command which is part of the standard ImageMagick kit. This allows you to have the power
|
|
753
|
-
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:
|
|
754
1014
|
|
|
755
|
-
|
|
1015
|
+
````bash
|
|
1016
|
+
$ sudo apt install libvips
|
|
1017
|
+
````
|
|
756
1018
|
|
|
757
|
-
|
|
1019
|
+
You also need to tell your uploader to use Vips:
|
|
1020
|
+
|
|
1021
|
+
````ruby
|
|
1022
|
+
class ImageFileUploader < CarrierWave::Uploader::Base
|
|
1023
|
+
include CarrierWave::Vips
|
|
1024
|
+
end
|
|
1025
|
+
````
|
|
758
1026
|
|
|
759
|
-
|
|
1027
|
+
### List of available processing methods:
|
|
760
1028
|
|
|
761
|
-
|
|
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>.
|
|
762
1031
|
|
|
763
|
-
|
|
764
|
-
|
|
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.
|
|
765
1038
|
|
|
766
|
-
|
|
767
|
-
class AvatarUploader < CarrierWave::Uploader::Base
|
|
768
|
-
include CarrierWave::MiniMagick
|
|
1039
|
+
#### Supported processing methods
|
|
769
1040
|
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
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).
|
|
773
1058
|
|
|
774
1059
|
## Migrating from Paperclip
|
|
775
1060
|
|
|
@@ -787,28 +1072,36 @@ details.
|
|
|
787
1072
|
Be sure to use mount_on to specify the correct column:
|
|
788
1073
|
|
|
789
1074
|
```ruby
|
|
790
|
-
mount_uploader :avatar, AvatarUploader, :
|
|
1075
|
+
mount_uploader :avatar, AvatarUploader, mount_on: :avatar_file_name
|
|
791
1076
|
```
|
|
792
1077
|
|
|
793
|
-
|
|
794
|
-
sensible compatibility mode. Patches for migrating from other solutions will be
|
|
795
|
-
happily accepted.
|
|
796
|
-
|
|
797
|
-
## i18n
|
|
1078
|
+
## I18n
|
|
798
1079
|
|
|
799
|
-
The Active Record validations use the Rails i18n framework. Add these keys to
|
|
1080
|
+
The Active Record validations use the Rails `i18n` framework. Add these keys to
|
|
800
1081
|
your translations file:
|
|
801
1082
|
|
|
802
1083
|
```yaml
|
|
803
1084
|
errors:
|
|
804
1085
|
messages:
|
|
805
|
-
carrierwave_processing_error:
|
|
806
|
-
carrierwave_integrity_error:
|
|
807
|
-
carrierwave_download_error:
|
|
808
|
-
|
|
809
|
-
|
|
1086
|
+
carrierwave_processing_error: failed to be processed
|
|
1087
|
+
carrierwave_integrity_error: is not of an allowed file type
|
|
1088
|
+
carrierwave_download_error: could not be downloaded
|
|
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?"
|
|
1094
|
+
min_size_error: "File size should be greater than %{min_size}"
|
|
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"
|
|
810
1100
|
```
|
|
811
1101
|
|
|
1102
|
+
The [`carrierwave-i18n`](https://github.com/carrierwaveuploader/carrierwave-i18n)
|
|
1103
|
+
library adds support for additional locales.
|
|
1104
|
+
|
|
812
1105
|
## Large files
|
|
813
1106
|
|
|
814
1107
|
By default, CarrierWave copies an uploaded file twice, first copying the file into the cache, then
|
|
@@ -822,6 +1115,7 @@ class MyUploader < CarrierWave::Uploader::Base
|
|
|
822
1115
|
def move_to_cache
|
|
823
1116
|
true
|
|
824
1117
|
end
|
|
1118
|
+
|
|
825
1119
|
def move_to_store
|
|
826
1120
|
true
|
|
827
1121
|
end
|
|
@@ -846,11 +1140,12 @@ end
|
|
|
846
1140
|
Will add these callbacks:
|
|
847
1141
|
|
|
848
1142
|
```ruby
|
|
849
|
-
after_save :store_avatar!
|
|
850
1143
|
before_save :write_avatar_identifier
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
1144
|
+
after_save :store_previous_changes_for_avatar
|
|
1145
|
+
after_commit :remove_avatar!, on: :destroy
|
|
1146
|
+
after_commit :mark_remove_avatar_false, on: :update
|
|
1147
|
+
after_commit :remove_previously_stored_avatar, on: :update
|
|
1148
|
+
after_commit :store_avatar!, on: [:create, :update]
|
|
854
1149
|
```
|
|
855
1150
|
|
|
856
1151
|
If you want to skip any of these callbacks (eg. you want to keep the existing
|
|
@@ -860,17 +1155,44 @@ avatar, even after uploading a new one), you can use ActiveRecord’s
|
|
|
860
1155
|
```ruby
|
|
861
1156
|
class User
|
|
862
1157
|
mount_uploader :avatar, AvatarUploader
|
|
863
|
-
skip_callback :
|
|
1158
|
+
skip_callback :commit, :after, :remove_previously_stored_avatar
|
|
1159
|
+
end
|
|
1160
|
+
```
|
|
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
|
|
864
1173
|
end
|
|
865
1174
|
```
|
|
866
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
|
+
|
|
867
1187
|
## Contributing to CarrierWave
|
|
868
1188
|
|
|
869
1189
|
See [CONTRIBUTING.md](https://github.com/carrierwaveuploader/carrierwave/blob/master/CONTRIBUTING.md)
|
|
870
1190
|
|
|
871
1191
|
## License
|
|
872
1192
|
|
|
873
|
-
|
|
1193
|
+
The MIT License (MIT)
|
|
1194
|
+
|
|
1195
|
+
Copyright (c) 2008 Jonas Nicklas
|
|
874
1196
|
|
|
875
1197
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
876
1198
|
a copy of this software and associated documentation files (the
|