carrierwave 1.3.1 → 3.0.5
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of carrierwave might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +238 -91
- 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 +167 -77
- data/lib/carrierwave/orm/activerecord.rb +15 -55
- data/lib/carrierwave/processing/mini_magick.rb +108 -123
- data/lib/carrierwave/processing/rmagick.rb +20 -18
- data/lib/carrierwave/processing/vips.rb +284 -0
- data/lib/carrierwave/processing.rb +1 -0
- data/lib/carrierwave/sanitized_file.rb +66 -73
- data/lib/carrierwave/storage/abstract.rb +5 -5
- data/lib/carrierwave/storage/file.rb +6 -5
- data/lib/carrierwave/storage/fog.rb +101 -64
- 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 +38 -19
- data/lib/carrierwave/uploader/content_type_allowlist.rb +62 -0
- data/lib/carrierwave/uploader/content_type_denylist.rb +62 -0
- data/lib/carrierwave/uploader/dimension.rb +66 -0
- data/lib/carrierwave/uploader/download.rb +2 -80
- 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 +42 -7
- data/lib/carrierwave/uploader/proxy.rb +17 -4
- data/lib/carrierwave/uploader/serialization.rb +1 -1
- data/lib/carrierwave/uploader/store.rb +47 -7
- data/lib/carrierwave/uploader/url.rb +7 -4
- data/lib/carrierwave/uploader/versions.rb +153 -105
- 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 +13 -17
- data/lib/generators/templates/{uploader.rb → uploader.rb.erb} +3 -3
- data/lib/generators/uploader_generator.rb +3 -3
- metadata +104 -38
- 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
@@ -30,7 +30,7 @@ module CarrierWave
|
|
30
30
|
#
|
31
31
|
# Google credentials contain the following keys:
|
32
32
|
# [:google_storage_access_key_id]
|
33
|
-
# [:
|
33
|
+
# [:google_storage_secret_access_key]
|
34
34
|
#
|
35
35
|
#
|
36
36
|
# Local credentials contain the following keys:
|
@@ -60,6 +60,14 @@ module CarrierWave
|
|
60
60
|
def connection_cache
|
61
61
|
@connection_cache ||= {}
|
62
62
|
end
|
63
|
+
|
64
|
+
def eager_load
|
65
|
+
# see #1198. This will hopefully no longer be necessary in future release of fog
|
66
|
+
fog_credentials = CarrierWave::Uploader::Base.fog_credentials
|
67
|
+
if fog_credentials.present?
|
68
|
+
CarrierWave::Storage::Fog.connection_cache[fog_credentials] ||= ::Fog::Storage.new(fog_credentials)
|
69
|
+
end
|
70
|
+
end
|
63
71
|
end
|
64
72
|
|
65
73
|
##
|
@@ -138,9 +146,10 @@ module CarrierWave
|
|
138
146
|
:key => uploader.fog_directory,
|
139
147
|
:public => uploader.fog_public
|
140
148
|
).files.all(:prefix => uploader.cache_dir).each do |file|
|
141
|
-
# generate_cache_id returns key
|
142
|
-
|
143
|
-
|
149
|
+
# generate_cache_id returns key formatted TIMEINT-PID(-COUNTER)-RND
|
150
|
+
matched = file.key.match(/(\d+)-\d+-\d+(?:-\d+)?/)
|
151
|
+
next unless matched
|
152
|
+
time = Time.at(matched[1].to_i)
|
144
153
|
file.destroy if time < (Time.now.utc - seconds)
|
145
154
|
end
|
146
155
|
end
|
@@ -153,7 +162,10 @@ module CarrierWave
|
|
153
162
|
end
|
154
163
|
|
155
164
|
class File
|
165
|
+
DEFAULT_S3_REGION = 'us-east-1'.freeze
|
166
|
+
|
156
167
|
include CarrierWave::Utilities::Uri
|
168
|
+
include CarrierWave::Utilities::FileName
|
157
169
|
|
158
170
|
##
|
159
171
|
# Current local path to file
|
@@ -177,7 +189,7 @@ module CarrierWave
|
|
177
189
|
|
178
190
|
##
|
179
191
|
# Return a temporary authenticated url to a private file, if available
|
180
|
-
# Only supported for AWS, Rackspace and
|
192
|
+
# Only supported for AWS, Rackspace, Google, AzureRM and Aliyun providers
|
181
193
|
#
|
182
194
|
# === Returns
|
183
195
|
#
|
@@ -186,26 +198,27 @@ module CarrierWave
|
|
186
198
|
# [NilClass] no authenticated url available
|
187
199
|
#
|
188
200
|
def authenticated_url(options = {})
|
189
|
-
if ['AWS', 'Google', 'Rackspace', 'OpenStack'].include?(
|
201
|
+
if ['AWS', 'Google', 'Rackspace', 'OpenStack', 'AzureRM', 'Aliyun', 'backblaze'].include?(fog_provider)
|
190
202
|
# avoid a get by using local references
|
191
203
|
local_directory = connection.directories.new(:key => @uploader.fog_directory)
|
192
204
|
local_file = local_directory.files.new(:key => path)
|
193
|
-
expire_at = ::Fog::Time.now
|
194
|
-
case
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
else
|
200
|
-
warn "Options hash not supported in #{local_file.class}. You may need to upgrade your Fog provider."
|
201
|
-
local_file.url(expire_at)
|
202
|
-
end
|
203
|
-
when 'Rackspace'
|
204
|
-
connection.get_object_https_url(@uploader.fog_directory, path, expire_at, options)
|
205
|
-
when 'OpenStack'
|
206
|
-
connection.get_object_https_url(@uploader.fog_directory, path, expire_at)
|
205
|
+
expire_at = options[:expire_at] || ::Fog::Time.now.since(@uploader.fog_authenticated_url_expiration.to_i)
|
206
|
+
case fog_provider
|
207
|
+
when 'AWS', 'Google'
|
208
|
+
# Older versions of fog-google do not support options as a parameter
|
209
|
+
if url_options_supported?(local_file)
|
210
|
+
local_file.url(expire_at, options)
|
207
211
|
else
|
212
|
+
warn "Options hash not supported in #{local_file.class}. You may need to upgrade your Fog provider."
|
208
213
|
local_file.url(expire_at)
|
214
|
+
end
|
215
|
+
when 'Rackspace', 'OpenStack'
|
216
|
+
connection.get_object_https_url(@uploader.fog_directory, path, expire_at, options)
|
217
|
+
when 'Aliyun'
|
218
|
+
expire_at -= Time.now
|
219
|
+
local_file.url(expire_at)
|
220
|
+
else
|
221
|
+
local_file.url(expire_at)
|
209
222
|
end
|
210
223
|
end
|
211
224
|
end
|
@@ -218,7 +231,7 @@ module CarrierWave
|
|
218
231
|
# [String] value of content-type
|
219
232
|
#
|
220
233
|
def content_type
|
221
|
-
@content_type ||
|
234
|
+
@content_type || file.try(:content_type)
|
222
235
|
end
|
223
236
|
|
224
237
|
##
|
@@ -241,19 +254,9 @@ module CarrierWave
|
|
241
254
|
#
|
242
255
|
def delete
|
243
256
|
# avoid a get by just using local reference
|
244
|
-
directory.files.new(:key => path).destroy
|
245
|
-
|
246
|
-
|
247
|
-
##
|
248
|
-
# Return extension of file
|
249
|
-
#
|
250
|
-
# === Returns
|
251
|
-
#
|
252
|
-
# [String] extension of file or nil if the file has no extension
|
253
|
-
#
|
254
|
-
def extension
|
255
|
-
path_elements = path.split('.')
|
256
|
-
path_elements.last if path_elements.size > 1
|
257
|
+
directory.files.new(:key => path).destroy.tap do |result|
|
258
|
+
@file = nil if result
|
259
|
+
end
|
257
260
|
end
|
258
261
|
|
259
262
|
##
|
@@ -282,16 +285,16 @@ module CarrierWave
|
|
282
285
|
#
|
283
286
|
# [String] contents of file
|
284
287
|
def read
|
285
|
-
file_body = file
|
288
|
+
file_body = file&.body
|
286
289
|
|
287
290
|
return if file_body.nil?
|
288
291
|
return file_body unless file_body.is_a?(::File)
|
289
292
|
|
290
|
-
# Fog::Storage::XXX::File#body could return the source file which was
|
291
|
-
read_source_file
|
293
|
+
# Fog::Storage::XXX::File#body could return the source file which was uploaded to the remote server.
|
294
|
+
return read_source_file if ::File.exist?(file_body.path)
|
292
295
|
|
293
296
|
# If the source file doesn't exist, the remote content is read
|
294
|
-
@file = nil
|
297
|
+
@file = nil
|
295
298
|
file.body
|
296
299
|
end
|
297
300
|
|
@@ -329,7 +332,7 @@ module CarrierWave
|
|
329
332
|
fog_file = new_file.to_file
|
330
333
|
@content_type ||= new_file.content_type
|
331
334
|
@file = directory.files.create({
|
332
|
-
:body => fog_file
|
335
|
+
:body => fog_file || new_file.read,
|
333
336
|
:content_type => @content_type,
|
334
337
|
:key => path,
|
335
338
|
:public => @uploader.fog_public
|
@@ -350,7 +353,7 @@ module CarrierWave
|
|
350
353
|
#
|
351
354
|
def public_url
|
352
355
|
encoded_path = encode_path(path)
|
353
|
-
if host = @uploader.asset_host
|
356
|
+
if (host = @uploader.asset_host)
|
354
357
|
if host.respond_to? :call
|
355
358
|
"#{host.call(self)}/#{encoded_path}"
|
356
359
|
else
|
@@ -367,15 +370,22 @@ module CarrierWave
|
|
367
370
|
protocol = @uploader.fog_use_ssl_for_aws ? "https" : "http"
|
368
371
|
|
369
372
|
subdomain_regex = /^(?:[a-z]|\d(?!\d{0,2}(?:\d{1,3}){3}$))(?:[a-z0-9\.]|(?![\-])|\-(?![\.])){1,61}[a-z0-9]$/
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
373
|
+
# To use the virtual-hosted style, the bucket name needs to be representable as a subdomain
|
374
|
+
use_virtual_hosted_style = @uploader.fog_directory.to_s =~ subdomain_regex && !(protocol == 'https' && @uploader.fog_directory =~ /\./)
|
375
|
+
|
376
|
+
region = @uploader.fog_credentials[:region].to_s
|
377
|
+
regional_host = case region
|
378
|
+
when DEFAULT_S3_REGION, ''
|
379
|
+
's3.amazonaws.com'
|
380
|
+
else
|
381
|
+
"s3.#{region}.amazonaws.com"
|
382
|
+
end
|
383
|
+
|
384
|
+
if use_virtual_hosted_style
|
385
|
+
regional_host = 's3-accelerate.amazonaws.com' if @uploader.fog_aws_accelerate
|
386
|
+
"#{protocol}://#{@uploader.fog_directory}.#{regional_host}/#{encoded_path}"
|
387
|
+
else # directory is not a valid subdomain, so use path style for access
|
388
|
+
"#{protocol}://#{regional_host}/#{@uploader.fog_directory}/#{encoded_path}"
|
379
389
|
end
|
380
390
|
end
|
381
391
|
when 'Google'
|
@@ -389,7 +399,7 @@ module CarrierWave
|
|
389
399
|
end
|
390
400
|
|
391
401
|
##
|
392
|
-
# Return url to file, if
|
402
|
+
# Return url to file, if available
|
393
403
|
#
|
394
404
|
# === Returns
|
395
405
|
#
|
@@ -415,7 +425,7 @@ module CarrierWave
|
|
415
425
|
# [NilClass] no file name available
|
416
426
|
#
|
417
427
|
def filename(options = {})
|
418
|
-
return unless file_url = url(options)
|
428
|
+
return unless (file_url = url(options))
|
419
429
|
CGI.unescape(file_url.split('?').first).gsub(/.*\/(.*?$)/, '\1')
|
420
430
|
end
|
421
431
|
|
@@ -431,10 +441,29 @@ module CarrierWave
|
|
431
441
|
# @return [CarrierWave::Storage::Fog::File] the location where the file will be stored.
|
432
442
|
#
|
433
443
|
def copy_to(new_path)
|
434
|
-
|
444
|
+
file.copy(@uploader.fog_directory, new_path, copy_options)
|
435
445
|
CarrierWave::Storage::Fog::File.new(@uploader, @base, new_path)
|
436
446
|
end
|
437
447
|
|
448
|
+
##
|
449
|
+
# Return the local file
|
450
|
+
#
|
451
|
+
# === Returns
|
452
|
+
#
|
453
|
+
# [File] The local file as Ruby's File class
|
454
|
+
# or
|
455
|
+
# [NilClass] When there's no file, or the file is remotely stored
|
456
|
+
#
|
457
|
+
def to_file
|
458
|
+
return nil unless file.body.is_a? ::File
|
459
|
+
|
460
|
+
if file.body.closed?
|
461
|
+
::File.open(file.body.path) # Reopen if it's already closed
|
462
|
+
else
|
463
|
+
file.body
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
438
467
|
private
|
439
468
|
|
440
469
|
##
|
@@ -456,12 +485,10 @@ module CarrierWave
|
|
456
485
|
# [Fog::#{provider}::Directory] containing directory
|
457
486
|
#
|
458
487
|
def directory
|
459
|
-
@directory ||=
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
)
|
464
|
-
end
|
488
|
+
@directory ||= connection.directories.new(
|
489
|
+
:key => @uploader.fog_directory,
|
490
|
+
:public => @uploader.fog_public
|
491
|
+
)
|
465
492
|
end
|
466
493
|
|
467
494
|
##
|
@@ -475,9 +502,19 @@ module CarrierWave
|
|
475
502
|
@file ||= directory.files.head(path)
|
476
503
|
end
|
477
504
|
|
505
|
+
def copy_options
|
506
|
+
options = {}
|
507
|
+
options.merge!(acl_header) if acl_header.present?
|
508
|
+
options[fog_provider == "Google" ? :content_type : 'Content-Type'] ||= content_type if content_type
|
509
|
+
options.merge(@uploader.fog_attributes)
|
510
|
+
end
|
511
|
+
|
478
512
|
def acl_header
|
479
|
-
|
513
|
+
case fog_provider
|
514
|
+
when 'AWS'
|
480
515
|
{ 'x-amz-acl' => @uploader.fog_public ? 'public-read' : 'private' }
|
516
|
+
when "Google"
|
517
|
+
@uploader.fog_public ? { destination_predefined_acl: "publicRead" } : {}
|
481
518
|
else
|
482
519
|
{}
|
483
520
|
end
|
@@ -487,14 +524,14 @@ module CarrierWave
|
|
487
524
|
@uploader.fog_credentials[:provider].to_s
|
488
525
|
end
|
489
526
|
|
490
|
-
def read_source_file
|
491
|
-
|
527
|
+
def read_source_file
|
528
|
+
source_file = to_file
|
529
|
+
return unless source_file
|
492
530
|
|
493
531
|
begin
|
494
|
-
|
495
|
-
file_body.read
|
532
|
+
source_file.read
|
496
533
|
ensure
|
497
|
-
|
534
|
+
source_file.close
|
498
535
|
end
|
499
536
|
end
|
500
537
|
|
data/lib/carrierwave/storage.rb
CHANGED
@@ -45,11 +45,11 @@ module CarrierWave
|
|
45
45
|
def matches?(actual)
|
46
46
|
@actual = actual
|
47
47
|
# Satisfy expectation here. Return false or raise an error if it's not met.
|
48
|
-
(File.stat(@actual.path).mode &
|
48
|
+
(File.stat(@actual.path).mode & 0o777) == @expected
|
49
49
|
end
|
50
50
|
|
51
51
|
def failure_message
|
52
|
-
"expected #{@actual.current_path.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode &
|
52
|
+
"expected #{@actual.current_path.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0o777).to_s(8)}"
|
53
53
|
end
|
54
54
|
|
55
55
|
def failure_message_when_negated
|
@@ -76,11 +76,11 @@ module CarrierWave
|
|
76
76
|
def matches?(actual)
|
77
77
|
@actual = actual
|
78
78
|
# Satisfy expectation here. Return false or raise an error if it's not met.
|
79
|
-
(File.stat(File.dirname
|
79
|
+
(File.stat(File.dirname(@actual.path)).mode & 0o777) == @expected
|
80
80
|
end
|
81
81
|
|
82
82
|
def failure_message
|
83
|
-
"expected #{File.dirname @actual.current_path.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode &
|
83
|
+
"expected #{File.dirname @actual.current_path.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0o777).to_s(8)}"
|
84
84
|
end
|
85
85
|
|
86
86
|
def failure_message_when_negated
|
@@ -341,9 +341,11 @@ module CarrierWave
|
|
341
341
|
begin
|
342
342
|
require 'rmagick'
|
343
343
|
rescue LoadError
|
344
|
-
|
345
|
-
|
346
|
-
|
344
|
+
begin
|
345
|
+
require 'RMagick'
|
346
|
+
rescue LoadError
|
347
|
+
puts "WARNING: Failed to require rmagick, image processing may fail!"
|
348
|
+
end
|
347
349
|
end
|
348
350
|
end
|
349
351
|
MagickWrapper.new(filename)
|
@@ -353,6 +355,7 @@ module CarrierWave
|
|
353
355
|
|
354
356
|
class MagickWrapper # :nodoc:
|
355
357
|
attr_reader :image
|
358
|
+
|
356
359
|
def width
|
357
360
|
image.columns
|
358
361
|
end
|
@@ -372,6 +375,7 @@ module CarrierWave
|
|
372
375
|
|
373
376
|
class MiniMagickWrapper # :nodoc:
|
374
377
|
attr_reader :image
|
378
|
+
|
375
379
|
def width
|
376
380
|
image[:width]
|
377
381
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
1
3
|
module CarrierWave
|
2
4
|
|
3
5
|
class FormNotMultipart < UploadError
|
@@ -22,10 +24,11 @@ module CarrierWave
|
|
22
24
|
# [String] a cache id in the format TIMEINT-PID-COUNTER-RND
|
23
25
|
#
|
24
26
|
def self.generate_cache_id
|
25
|
-
[
|
26
|
-
|
27
|
-
|
28
|
-
'%04d' %
|
27
|
+
[
|
28
|
+
Time.now.utc.to_i,
|
29
|
+
SecureRandom.random_number(1_000_000_000_000_000),
|
30
|
+
'%04d' % (CarrierWave::CacheCounter.increment % 10_000),
|
31
|
+
'%04d' % SecureRandom.random_number(10_000)
|
29
32
|
].map(&:to_s).join('-')
|
30
33
|
end
|
31
34
|
|
@@ -36,6 +39,16 @@ module CarrierWave
|
|
36
39
|
include CarrierWave::Uploader::Callbacks
|
37
40
|
include CarrierWave::Uploader::Configuration
|
38
41
|
|
42
|
+
included do
|
43
|
+
prepend Module.new {
|
44
|
+
def initialize(*)
|
45
|
+
super
|
46
|
+
@staged = false
|
47
|
+
end
|
48
|
+
}
|
49
|
+
attr_accessor :staged
|
50
|
+
end
|
51
|
+
|
39
52
|
module ClassMethods
|
40
53
|
|
41
54
|
##
|
@@ -52,7 +65,7 @@ module CarrierWave
|
|
52
65
|
# It's recommended that you keep cache files in one place only.
|
53
66
|
#
|
54
67
|
def clean_cached_files!(seconds=60*60*24)
|
55
|
-
cache_storage.new(
|
68
|
+
(cache_storage || storage).new(new).clean_cache!(seconds)
|
56
69
|
end
|
57
70
|
end
|
58
71
|
|
@@ -64,7 +77,7 @@ module CarrierWave
|
|
64
77
|
# [Bool] whether the current file is cached
|
65
78
|
#
|
66
79
|
def cached?
|
67
|
-
|
80
|
+
!!@cache_id
|
68
81
|
end
|
69
82
|
|
70
83
|
##
|
@@ -78,14 +91,8 @@ module CarrierWave
|
|
78
91
|
end
|
79
92
|
|
80
93
|
def sanitized_file
|
81
|
-
|
82
|
-
|
83
|
-
sanitized = CarrierWave::Storage::Fog.new(self).retrieve!(File.basename(_content.path))
|
84
|
-
else
|
85
|
-
sanitized = SanitizedFile.new :tempfile => StringIO.new(_content),
|
86
|
-
:filename => File.basename(path), :content_type => file.content_type
|
87
|
-
end
|
88
|
-
sanitized
|
94
|
+
ActiveSupport::Deprecation.warn('#sanitized_file is deprecated, use #file instead.')
|
95
|
+
file
|
89
96
|
end
|
90
97
|
|
91
98
|
##
|
@@ -96,7 +103,7 @@ module CarrierWave
|
|
96
103
|
# [String] a cache name, in the format TIMEINT-PID-COUNTER-RND/filename.txt
|
97
104
|
#
|
98
105
|
def cache_name
|
99
|
-
File.join(cache_id,
|
106
|
+
File.join(cache_id, original_filename) if cache_id && original_filename
|
100
107
|
end
|
101
108
|
|
102
109
|
##
|
@@ -104,7 +111,7 @@ module CarrierWave
|
|
104
111
|
#
|
105
112
|
# By default, cache!() uses copy_to(), which operates by copying the file
|
106
113
|
# to the cache, then deleting the original file. If move_to_cache() is
|
107
|
-
#
|
114
|
+
# overridden to return true, then cache!() uses move_to(), which simply
|
108
115
|
# moves the file to the cache. Useful for large files.
|
109
116
|
#
|
110
117
|
# === Parameters
|
@@ -115,7 +122,7 @@ module CarrierWave
|
|
115
122
|
#
|
116
123
|
# [CarrierWave::FormNotMultipart] if the assigned parameter is a string
|
117
124
|
#
|
118
|
-
def cache!(new_file =
|
125
|
+
def cache!(new_file = file)
|
119
126
|
new_file = CarrierWave::SanitizedFile.new(new_file)
|
120
127
|
return if new_file.empty?
|
121
128
|
|
@@ -123,6 +130,8 @@ module CarrierWave
|
|
123
130
|
|
124
131
|
self.cache_id = CarrierWave.generate_cache_id unless cache_id
|
125
132
|
|
133
|
+
@identifier = nil
|
134
|
+
@staged = true
|
126
135
|
@filename = new_file.filename
|
127
136
|
self.original_filename = new_file.filename
|
128
137
|
|
@@ -156,8 +165,9 @@ module CarrierWave
|
|
156
165
|
def retrieve_from_cache!(cache_name)
|
157
166
|
with_callbacks(:retrieve_from_cache, cache_name) do
|
158
167
|
self.cache_id, self.original_filename = cache_name.to_s.split('/', 2)
|
168
|
+
@staged = true
|
159
169
|
@filename = original_filename
|
160
|
-
@file = cache_storage.retrieve_from_cache!(
|
170
|
+
@file = cache_storage.retrieve_from_cache!(full_original_filename)
|
161
171
|
end
|
162
172
|
end
|
163
173
|
|
@@ -172,20 +182,21 @@ module CarrierWave
|
|
172
182
|
#
|
173
183
|
# [String] the cache path
|
174
184
|
#
|
175
|
-
def cache_path(for_file=
|
185
|
+
def cache_path(for_file=full_original_filename)
|
176
186
|
File.join(*[cache_dir, @cache_id, for_file].compact)
|
177
187
|
end
|
178
188
|
|
189
|
+
protected
|
190
|
+
|
191
|
+
attr_reader :cache_id
|
192
|
+
|
179
193
|
private
|
180
194
|
|
181
195
|
def workfile_path(for_file=original_filename)
|
182
196
|
File.join(CarrierWave.tmp_path, @cache_id, version_name.to_s, for_file)
|
183
197
|
end
|
184
198
|
|
185
|
-
attr_reader :
|
186
|
-
|
187
|
-
# We can override the full_original_filename method in other modules
|
188
|
-
alias_method :full_original_filename, :original_filename
|
199
|
+
attr_reader :original_filename
|
189
200
|
|
190
201
|
def cache_id=(cache_id)
|
191
202
|
# Earlier version used 3 part cache_id. Thus we should allow for
|
@@ -200,7 +211,12 @@ module CarrierWave
|
|
200
211
|
end
|
201
212
|
|
202
213
|
def cache_storage
|
203
|
-
@cache_storage ||= self.class.cache_storage.new(self)
|
214
|
+
@cache_storage ||= (self.class.cache_storage || self.class.storage).new(self)
|
215
|
+
end
|
216
|
+
|
217
|
+
# We can override the full_original_filename method in other modules
|
218
|
+
def full_original_filename
|
219
|
+
forcing_extension(original_filename)
|
204
220
|
end
|
205
221
|
end # Cache
|
206
222
|
end # Uploader
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'carrierwave/downloader/base'
|
2
|
+
|
1
3
|
module CarrierWave
|
2
4
|
|
3
5
|
module Uploader
|
@@ -21,9 +23,11 @@ module CarrierWave
|
|
21
23
|
add_config :move_to_cache
|
22
24
|
add_config :move_to_store
|
23
25
|
add_config :remove_previously_stored_files_after_update
|
26
|
+
add_config :downloader
|
27
|
+
add_config :force_extension
|
24
28
|
|
25
29
|
# fog
|
26
|
-
|
30
|
+
add_deprecated_config :fog_provider
|
27
31
|
add_config :fog_attributes
|
28
32
|
add_config :fog_credentials
|
29
33
|
add_config :fog_directory
|
@@ -41,6 +45,8 @@ module CarrierWave
|
|
41
45
|
add_config :validate_download
|
42
46
|
add_config :mount_on
|
43
47
|
add_config :cache_only
|
48
|
+
add_config :download_retry_count
|
49
|
+
add_config :download_retry_wait_time
|
44
50
|
|
45
51
|
# set default values
|
46
52
|
reset_config
|
@@ -74,7 +80,7 @@ module CarrierWave
|
|
74
80
|
def storage(storage = nil)
|
75
81
|
case storage
|
76
82
|
when Symbol
|
77
|
-
if storage_engine = storage_engines[storage]
|
83
|
+
if (storage_engine = storage_engines[storage])
|
78
84
|
self._storage = eval storage_engine
|
79
85
|
else
|
80
86
|
raise CarrierWave::UnknownStorageError, "Unknown storage: #{storage}"
|
@@ -107,8 +113,8 @@ module CarrierWave
|
|
107
113
|
# cache_storage CarrierWave::Storage::File
|
108
114
|
# cache_storage MyCustomStorageEngine
|
109
115
|
#
|
110
|
-
def cache_storage(storage =
|
111
|
-
|
116
|
+
def cache_storage(storage = false)
|
117
|
+
unless storage == false
|
112
118
|
self._cache_storage = storage.is_a?(Symbol) ? eval(storage_engines[storage]) : storage
|
113
119
|
end
|
114
120
|
_cache_storage
|
@@ -119,16 +125,8 @@ module CarrierWave
|
|
119
125
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
120
126
|
@#{name} = nil
|
121
127
|
|
122
|
-
def self.eager_load_fog(fog_credentials)
|
123
|
-
# see #1198. This will hopefully no longer be necessary after fog 2.0
|
124
|
-
require self.fog_provider
|
125
|
-
require 'carrierwave/storage/fog'
|
126
|
-
Fog::Storage.new(fog_credentials) if fog_credentials.present?
|
127
|
-
end unless defined? eager_load_fog
|
128
|
-
|
129
128
|
def self.#{name}(value=nil)
|
130
|
-
@#{name} = value
|
131
|
-
eager_load_fog(value) if value && '#{name}' == 'fog_credentials'
|
129
|
+
@#{name} = value unless value.nil?
|
132
130
|
return @#{name} if self.object_id == #{self.object_id} || defined?(@#{name})
|
133
131
|
name = superclass.#{name}
|
134
132
|
return nil if name.nil? && !instance_variable_defined?(:@#{name})
|
@@ -136,12 +134,10 @@ module CarrierWave
|
|
136
134
|
end
|
137
135
|
|
138
136
|
def self.#{name}=(value)
|
139
|
-
eager_load_fog(value) if '#{name}' == 'fog_credentials' && value.present?
|
140
137
|
@#{name} = value
|
141
138
|
end
|
142
139
|
|
143
140
|
def #{name}=(value)
|
144
|
-
self.class.eager_load_fog(value) if '#{name}' == 'fog_credentials' && value.present?
|
145
141
|
@#{name} = value
|
146
142
|
end
|
147
143
|
|
@@ -157,6 +153,26 @@ module CarrierWave
|
|
157
153
|
RUBY
|
158
154
|
end
|
159
155
|
|
156
|
+
def add_deprecated_config(name)
|
157
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
158
|
+
def self.#{name}(value=nil)
|
159
|
+
ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.#{name}=(value)
|
163
|
+
ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
|
164
|
+
end
|
165
|
+
|
166
|
+
def #{name}=(value)
|
167
|
+
ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
|
168
|
+
end
|
169
|
+
|
170
|
+
def #{name}
|
171
|
+
ActiveSupport::Deprecation.warn "##{name} is deprecated and has no effect"
|
172
|
+
end
|
173
|
+
RUBY
|
174
|
+
end
|
175
|
+
|
160
176
|
def configure
|
161
177
|
yield self
|
162
178
|
end
|
@@ -166,15 +182,14 @@ module CarrierWave
|
|
166
182
|
#
|
167
183
|
def reset_config
|
168
184
|
configure do |config|
|
169
|
-
config.permissions =
|
170
|
-
config.directory_permissions =
|
185
|
+
config.permissions = 0o644
|
186
|
+
config.directory_permissions = 0o755
|
171
187
|
config.storage_engines = {
|
172
188
|
:file => "CarrierWave::Storage::File",
|
173
189
|
:fog => "CarrierWave::Storage::Fog"
|
174
190
|
}
|
175
191
|
config.storage = :file
|
176
|
-
config.cache_storage =
|
177
|
-
config.fog_provider = 'fog'
|
192
|
+
config.cache_storage = nil
|
178
193
|
config.fog_attributes = {}
|
179
194
|
config.fog_credentials = {}
|
180
195
|
config.fog_public = true
|
@@ -187,6 +202,8 @@ module CarrierWave
|
|
187
202
|
config.move_to_cache = false
|
188
203
|
config.move_to_store = false
|
189
204
|
config.remove_previously_stored_files_after_update = true
|
205
|
+
config.downloader = CarrierWave::Downloader::Base
|
206
|
+
config.force_extension = false
|
190
207
|
config.ignore_integrity_errors = true
|
191
208
|
config.ignore_processing_errors = true
|
192
209
|
config.ignore_download_errors = true
|
@@ -197,6 +214,8 @@ module CarrierWave
|
|
197
214
|
config.base_path = CarrierWave.base_path
|
198
215
|
config.enable_processing = true
|
199
216
|
config.ensure_multipart_form = true
|
217
|
+
config.download_retry_count = 0
|
218
|
+
config.download_retry_wait_time = 5
|
200
219
|
end
|
201
220
|
end
|
202
221
|
end
|