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
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module CarrierWave
|
4
2
|
module Storage
|
5
3
|
|
@@ -9,13 +7,17 @@ module CarrierWave
|
|
9
7
|
# pretty much it.
|
10
8
|
#
|
11
9
|
class File < Abstract
|
10
|
+
def initialize(*)
|
11
|
+
super
|
12
|
+
@cache_called = nil
|
13
|
+
end
|
12
14
|
|
13
15
|
##
|
14
16
|
# Move the file to the uploader's store path.
|
15
17
|
#
|
16
18
|
# By default, store!() uses copy_to(), which operates by copying the file
|
17
19
|
# from the cache to the store, then deleting the file from the cache.
|
18
|
-
# If move_to_store() is
|
20
|
+
# If move_to_store() is overridden to return true, then store!() uses move_to(),
|
19
21
|
# which simply moves the file from cache to store. Useful for large files.
|
20
22
|
#
|
21
23
|
# === Parameters
|
@@ -51,6 +53,72 @@ module CarrierWave
|
|
51
53
|
CarrierWave::SanitizedFile.new(path)
|
52
54
|
end
|
53
55
|
|
56
|
+
##
|
57
|
+
# Stores given file to cache directory.
|
58
|
+
#
|
59
|
+
# === Parameters
|
60
|
+
#
|
61
|
+
# [new_file (File, IOString, Tempfile)] any kind of file object
|
62
|
+
#
|
63
|
+
# === Returns
|
64
|
+
#
|
65
|
+
# [CarrierWave::SanitizedFile] a sanitized file
|
66
|
+
#
|
67
|
+
def cache!(new_file)
|
68
|
+
new_file.move_to(::File.expand_path(uploader.cache_path, uploader.root), uploader.permissions, uploader.directory_permissions, true)
|
69
|
+
rescue Errno::EMLINK, Errno::ENOSPC => e
|
70
|
+
raise(e) if @cache_called
|
71
|
+
@cache_called = true
|
72
|
+
|
73
|
+
# NOTE: Remove cached files older than 10 minutes
|
74
|
+
clean_cache!(600)
|
75
|
+
|
76
|
+
cache!(new_file)
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# Retrieves the file with the given cache_name from the cache.
|
81
|
+
#
|
82
|
+
# === Parameters
|
83
|
+
#
|
84
|
+
# [cache_name (String)] uniquely identifies a cache file
|
85
|
+
#
|
86
|
+
# === Raises
|
87
|
+
#
|
88
|
+
# [CarrierWave::InvalidParameter] if the cache_name is incorrectly formatted.
|
89
|
+
#
|
90
|
+
def retrieve_from_cache!(identifier)
|
91
|
+
CarrierWave::SanitizedFile.new(::File.expand_path(uploader.cache_path(identifier), uploader.root))
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# Deletes a cache dir
|
96
|
+
#
|
97
|
+
def delete_dir!(path)
|
98
|
+
if path
|
99
|
+
begin
|
100
|
+
Dir.rmdir(::File.expand_path(path, uploader.root))
|
101
|
+
rescue Errno::ENOENT
|
102
|
+
# Ignore: path does not exist
|
103
|
+
rescue Errno::ENOTDIR
|
104
|
+
# Ignore: path is not a dir
|
105
|
+
rescue Errno::ENOTEMPTY, Errno::EEXIST
|
106
|
+
# Ignore: dir is not empty
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def clean_cache!(seconds)
|
112
|
+
Dir.glob(::File.expand_path(::File.join(uploader.cache_dir, '*'), uploader.root)).each do |dir|
|
113
|
+
# generate_cache_id returns key formatted TIMEINT-PID(-COUNTER)-RND
|
114
|
+
matched = dir.scan(/(\d+)-\d+-\d+(?:-\d+)?/).first
|
115
|
+
next unless matched
|
116
|
+
time = Time.at(matched[0].to_i)
|
117
|
+
if time < (Time.now.utc - seconds)
|
118
|
+
FileUtils.rm_rf(dir)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
54
122
|
end # File
|
55
123
|
end # Storage
|
56
124
|
end # CarrierWave
|
@@ -1,5 +1,3 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
module CarrierWave
|
4
2
|
module Storage
|
5
3
|
|
@@ -18,6 +16,10 @@ module CarrierWave
|
|
18
16
|
# [:fog_authenticated_url_expiration] (optional) time (in seconds) that authenticated urls
|
19
17
|
# will be valid, when fog_public is false and provider is AWS or Google, defaults to 600
|
20
18
|
# [:fog_use_ssl_for_aws] (optional) #public_url will use https for the AWS generated URL]
|
19
|
+
# [:fog_aws_accelerate] (optional) #public_url will use s3-accelerate subdomain
|
20
|
+
# instead of s3, defaults to false
|
21
|
+
# [:fog_aws_fips] (optional) #public_url will use s3-fips subdomain
|
22
|
+
# instead of s3, defaults to false
|
21
23
|
#
|
22
24
|
#
|
23
25
|
# AWS credentials contain the following keys:
|
@@ -25,12 +27,12 @@ module CarrierWave
|
|
25
27
|
# [:aws_access_key_id]
|
26
28
|
# [:aws_secret_access_key]
|
27
29
|
# [:region] (optional) defaults to 'us-east-1'
|
28
|
-
# :region should be one of ['eu-west-1', 'us-east-1', 'ap-southeast-1', 'us-west-1', 'ap-northeast-1']
|
30
|
+
# :region should be one of ['eu-west-1', 'us-east-1', 'ap-southeast-1', 'us-west-1', 'ap-northeast-1', 'eu-central-1']
|
29
31
|
#
|
30
32
|
#
|
31
33
|
# Google credentials contain the following keys:
|
32
34
|
# [:google_storage_access_key_id]
|
33
|
-
# [:
|
35
|
+
# [:google_storage_secret_access_key]
|
34
36
|
#
|
35
37
|
#
|
36
38
|
# Local credentials contain the following keys:
|
@@ -60,6 +62,14 @@ module CarrierWave
|
|
60
62
|
def connection_cache
|
61
63
|
@connection_cache ||= {}
|
62
64
|
end
|
65
|
+
|
66
|
+
def eager_load
|
67
|
+
# see #1198. This will hopefully no longer be necessary in future release of fog
|
68
|
+
fog_credentials = CarrierWave::Uploader::Base.fog_credentials
|
69
|
+
if fog_credentials.present?
|
70
|
+
CarrierWave::Storage::Fog.connection_cache[fog_credentials] ||= ::Fog::Storage.new(fog_credentials)
|
71
|
+
end
|
72
|
+
end
|
63
73
|
end
|
64
74
|
|
65
75
|
##
|
@@ -94,6 +104,58 @@ module CarrierWave
|
|
94
104
|
CarrierWave::Storage::Fog::File.new(uploader, self, uploader.store_path(identifier))
|
95
105
|
end
|
96
106
|
|
107
|
+
##
|
108
|
+
# Stores given file to cache directory.
|
109
|
+
#
|
110
|
+
# === Parameters
|
111
|
+
#
|
112
|
+
# [new_file (File, IOString, Tempfile)] any kind of file object
|
113
|
+
#
|
114
|
+
# === Returns
|
115
|
+
#
|
116
|
+
# [CarrierWave::SanitizedFile] a sanitized file
|
117
|
+
#
|
118
|
+
def cache!(new_file)
|
119
|
+
f = CarrierWave::Storage::Fog::File.new(uploader, self, uploader.cache_path)
|
120
|
+
f.store(new_file)
|
121
|
+
f
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# Retrieves the file with the given cache_name from the cache.
|
126
|
+
#
|
127
|
+
# === Parameters
|
128
|
+
#
|
129
|
+
# [cache_name (String)] uniquely identifies a cache file
|
130
|
+
#
|
131
|
+
# === Raises
|
132
|
+
#
|
133
|
+
# [CarrierWave::InvalidParameter] if the cache_name is incorrectly formatted.
|
134
|
+
#
|
135
|
+
def retrieve_from_cache!(identifier)
|
136
|
+
CarrierWave::Storage::Fog::File.new(uploader, self, uploader.cache_path(identifier))
|
137
|
+
end
|
138
|
+
|
139
|
+
##
|
140
|
+
# Deletes a cache dir
|
141
|
+
#
|
142
|
+
def delete_dir!(path)
|
143
|
+
# do nothing, because there's no such things as 'empty directory'
|
144
|
+
end
|
145
|
+
|
146
|
+
def clean_cache!(seconds)
|
147
|
+
connection.directories.new(
|
148
|
+
:key => uploader.fog_directory,
|
149
|
+
:public => uploader.fog_public
|
150
|
+
).files.all(:prefix => uploader.cache_dir).each do |file|
|
151
|
+
# generate_cache_id returns key formatted TIMEINT-PID(-COUNTER)-RND
|
152
|
+
matched = file.key.match(/(\d+)-\d+-\d+(?:-\d+)?/)
|
153
|
+
next unless matched
|
154
|
+
time = Time.at(matched[1].to_i)
|
155
|
+
file.destroy if time < (Time.now.utc - seconds)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
97
159
|
def connection
|
98
160
|
@connection ||= begin
|
99
161
|
options = credentials = uploader.fog_credentials
|
@@ -102,7 +164,10 @@ module CarrierWave
|
|
102
164
|
end
|
103
165
|
|
104
166
|
class File
|
167
|
+
DEFAULT_S3_REGION = 'us-east-1'.freeze
|
168
|
+
|
105
169
|
include CarrierWave::Utilities::Uri
|
170
|
+
include CarrierWave::Utilities::FileName
|
106
171
|
|
107
172
|
##
|
108
173
|
# Current local path to file
|
@@ -126,7 +191,7 @@ module CarrierWave
|
|
126
191
|
|
127
192
|
##
|
128
193
|
# Return a temporary authenticated url to a private file, if available
|
129
|
-
# Only supported for AWS, Rackspace and
|
194
|
+
# Only supported for AWS, Rackspace, Google, AzureRM and Aliyun providers
|
130
195
|
#
|
131
196
|
# === Returns
|
132
197
|
#
|
@@ -135,19 +200,28 @@ module CarrierWave
|
|
135
200
|
# [NilClass] no authenticated url available
|
136
201
|
#
|
137
202
|
def authenticated_url(options = {})
|
138
|
-
if ['AWS', 'Google', 'Rackspace', 'OpenStack'].include?(
|
203
|
+
if ['AWS', 'Google', 'Rackspace', 'OpenStack', 'AzureRM', 'Aliyun', 'backblaze'].include?(fog_provider)
|
139
204
|
# avoid a get by using local references
|
140
205
|
local_directory = connection.directories.new(:key => @uploader.fog_directory)
|
141
206
|
local_file = local_directory.files.new(:key => path)
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
207
|
+
expire_at = options[:expire_at] || ::Fog::Time.now.since(@uploader.fog_authenticated_url_expiration.to_i)
|
208
|
+
case fog_provider
|
209
|
+
when 'AWS', 'Google'
|
210
|
+
# Older versions of fog-google do not support options as a parameter
|
211
|
+
if url_options_supported?(local_file)
|
212
|
+
local_file.url(expire_at, options)
|
213
|
+
else
|
214
|
+
warn "Options hash not supported in #{local_file.class}. You may need to upgrade your Fog provider."
|
215
|
+
local_file.url(expire_at)
|
216
|
+
end
|
217
|
+
when 'Rackspace', 'OpenStack'
|
218
|
+
connection.get_object_https_url(@uploader.fog_directory, path, expire_at, options)
|
219
|
+
when 'Aliyun'
|
220
|
+
expire_at -= Time.now
|
221
|
+
local_file.url(expire_at)
|
146
222
|
else
|
147
|
-
local_file.url(
|
223
|
+
local_file.url(expire_at)
|
148
224
|
end
|
149
|
-
else
|
150
|
-
nil
|
151
225
|
end
|
152
226
|
end
|
153
227
|
|
@@ -159,7 +233,7 @@ module CarrierWave
|
|
159
233
|
# [String] value of content-type
|
160
234
|
#
|
161
235
|
def content_type
|
162
|
-
@content_type || file.content_type
|
236
|
+
@content_type || file.try(:content_type)
|
163
237
|
end
|
164
238
|
|
165
239
|
##
|
@@ -182,19 +256,9 @@ module CarrierWave
|
|
182
256
|
#
|
183
257
|
def delete
|
184
258
|
# avoid a get by just using local reference
|
185
|
-
directory.files.new(:key => path).destroy
|
186
|
-
|
187
|
-
|
188
|
-
##
|
189
|
-
# Return extension of file
|
190
|
-
#
|
191
|
-
# === Returns
|
192
|
-
#
|
193
|
-
# [String] extension of file or nil if the file has no extension
|
194
|
-
#
|
195
|
-
def extension
|
196
|
-
path_elements = path.split('.')
|
197
|
-
path_elements.last if path_elements.size > 1
|
259
|
+
directory.files.new(:key => path).destroy.tap do |result|
|
260
|
+
@file = nil if result
|
261
|
+
end
|
198
262
|
end
|
199
263
|
|
200
264
|
##
|
@@ -213,7 +277,7 @@ module CarrierWave
|
|
213
277
|
end
|
214
278
|
|
215
279
|
def initialize(uploader, base, path)
|
216
|
-
@uploader, @base, @path = uploader, base, path
|
280
|
+
@uploader, @base, @path, @content_type = uploader, base, path, nil
|
217
281
|
end
|
218
282
|
|
219
283
|
##
|
@@ -223,6 +287,16 @@ module CarrierWave
|
|
223
287
|
#
|
224
288
|
# [String] contents of file
|
225
289
|
def read
|
290
|
+
file_body = file&.body
|
291
|
+
|
292
|
+
return if file_body.nil?
|
293
|
+
return file_body unless file_body.is_a?(::File)
|
294
|
+
|
295
|
+
# Fog::Storage::XXX::File#body could return the source file which was uploaded to the remote server.
|
296
|
+
return read_source_file if ::File.exist?(file_body.path)
|
297
|
+
|
298
|
+
# If the source file doesn't exist, the remote content is read
|
299
|
+
@file = nil
|
226
300
|
file.body
|
227
301
|
end
|
228
302
|
|
@@ -234,7 +308,16 @@ module CarrierWave
|
|
234
308
|
# [Integer] size of file body
|
235
309
|
#
|
236
310
|
def size
|
237
|
-
file.content_length
|
311
|
+
file.nil? ? 0 : file.content_length
|
312
|
+
end
|
313
|
+
|
314
|
+
##
|
315
|
+
# === Returns
|
316
|
+
#
|
317
|
+
# [Boolean] whether the file is non-existent or empty
|
318
|
+
#
|
319
|
+
def empty?
|
320
|
+
!exists? || size.zero?
|
238
321
|
end
|
239
322
|
|
240
323
|
##
|
@@ -244,7 +327,7 @@ module CarrierWave
|
|
244
327
|
#
|
245
328
|
# [Boolean] true if file exists or false
|
246
329
|
def exists?
|
247
|
-
!!
|
330
|
+
!!file
|
248
331
|
end
|
249
332
|
|
250
333
|
##
|
@@ -254,15 +337,19 @@ module CarrierWave
|
|
254
337
|
#
|
255
338
|
# [Boolean] true on success or raises error
|
256
339
|
def store(new_file)
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
340
|
+
if new_file.is_a?(self.class)
|
341
|
+
new_file.copy_to(path)
|
342
|
+
else
|
343
|
+
fog_file = new_file.to_file
|
344
|
+
@content_type ||= new_file.content_type
|
345
|
+
@file = directory.files.create({
|
346
|
+
:body => fog_file || new_file.read,
|
347
|
+
:content_type => @content_type,
|
348
|
+
:key => path,
|
349
|
+
:public => @uploader.fog_public
|
350
|
+
}.merge(@uploader.fog_attributes))
|
351
|
+
fog_file.close if fog_file && !fog_file.closed?
|
352
|
+
end
|
266
353
|
true
|
267
354
|
end
|
268
355
|
|
@@ -277,7 +364,7 @@ module CarrierWave
|
|
277
364
|
#
|
278
365
|
def public_url
|
279
366
|
encoded_path = encode_path(path)
|
280
|
-
if host = @uploader.asset_host
|
367
|
+
if (host = @uploader.asset_host)
|
281
368
|
if host.respond_to? :call
|
282
369
|
"#{host.call(self)}/#{encoded_path}"
|
283
370
|
else
|
@@ -285,23 +372,38 @@ module CarrierWave
|
|
285
372
|
end
|
286
373
|
else
|
287
374
|
# AWS/Google optimized for speed over correctness
|
288
|
-
case
|
375
|
+
case fog_provider
|
289
376
|
when 'AWS'
|
290
377
|
# check if some endpoint is set in fog_credentials
|
291
378
|
if @uploader.fog_credentials.has_key?(:endpoint)
|
379
|
+
raise 'fog_aws_fips = true is incompatible with :endpoint, as FIPS endpoints do not support path-style URLs.' if @uploader.fog_aws_fips
|
292
380
|
"#{@uploader.fog_credentials[:endpoint]}/#{@uploader.fog_directory}/#{encoded_path}"
|
293
381
|
else
|
294
382
|
protocol = @uploader.fog_use_ssl_for_aws ? "https" : "http"
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
383
|
+
|
384
|
+
subdomain_regex = /^(?:[a-z]|\d(?!\d{0,2}(?:\d{1,3}){3}$))(?:[a-z0-9\.]|(?![\-])|\-(?![\.])){1,61}[a-z0-9]$/
|
385
|
+
# To use the virtual-hosted style, the bucket name needs to be representable as a subdomain
|
386
|
+
use_virtual_hosted_style = @uploader.fog_directory.to_s =~ subdomain_regex && !(protocol == 'https' && @uploader.fog_directory =~ /\./)
|
387
|
+
|
388
|
+
region = @uploader.fog_credentials[:region].to_s
|
389
|
+
regional_host = 's3.amazonaws.com' # used for DEFAULT_S3_REGION or no region set
|
390
|
+
if @uploader.fog_aws_fips
|
391
|
+
regional_host = "s3-fips.#{region}.amazonaws.com" # https://aws.amazon.com/compliance/fips/
|
392
|
+
elsif ![DEFAULT_S3_REGION, ''].include?(region)
|
393
|
+
regional_host = "s3.#{region}.amazonaws.com"
|
394
|
+
end
|
395
|
+
|
396
|
+
if use_virtual_hosted_style
|
397
|
+
regional_host = 's3-accelerate.amazonaws.com' if @uploader.fog_aws_accelerate
|
398
|
+
"#{protocol}://#{@uploader.fog_directory}.#{regional_host}/#{encoded_path}"
|
399
|
+
else # directory is not a valid subdomain, so use path style for access
|
400
|
+
raise 'FIPS Endpoints can only be used with Virtual Hosted-Style addressing.' if @uploader.fog_aws_fips
|
401
|
+
"#{protocol}://#{regional_host}/#{@uploader.fog_directory}/#{encoded_path}"
|
301
402
|
end
|
302
403
|
end
|
303
404
|
when 'Google'
|
304
|
-
|
405
|
+
# https://cloud.google.com/storage/docs/access-public-data
|
406
|
+
"https://storage.googleapis.com/#{@uploader.fog_directory}/#{encoded_path}"
|
305
407
|
else
|
306
408
|
# avoid a get by just using local reference
|
307
409
|
directory.files.new(:key => path).public_url
|
@@ -310,7 +412,7 @@ module CarrierWave
|
|
310
412
|
end
|
311
413
|
|
312
414
|
##
|
313
|
-
# Return url to file, if
|
415
|
+
# Return url to file, if available
|
314
416
|
#
|
315
417
|
# === Returns
|
316
418
|
#
|
@@ -336,8 +438,42 @@ module CarrierWave
|
|
336
438
|
# [NilClass] no file name available
|
337
439
|
#
|
338
440
|
def filename(options = {})
|
339
|
-
|
340
|
-
|
441
|
+
return unless (file_url = url(options))
|
442
|
+
CGI.unescape(file_url.split('?').first).gsub(/.*\/(.*?$)/, '\1')
|
443
|
+
end
|
444
|
+
|
445
|
+
##
|
446
|
+
# Creates a copy of this file and returns it.
|
447
|
+
#
|
448
|
+
# === Parameters
|
449
|
+
#
|
450
|
+
# [new_path (String)] The path where the file should be copied to.
|
451
|
+
#
|
452
|
+
# === Returns
|
453
|
+
#
|
454
|
+
# @return [CarrierWave::Storage::Fog::File] the location where the file will be stored.
|
455
|
+
#
|
456
|
+
def copy_to(new_path)
|
457
|
+
file.copy(@uploader.fog_directory, new_path, copy_options)
|
458
|
+
CarrierWave::Storage::Fog::File.new(@uploader, @base, new_path)
|
459
|
+
end
|
460
|
+
|
461
|
+
##
|
462
|
+
# Return the local file
|
463
|
+
#
|
464
|
+
# === Returns
|
465
|
+
#
|
466
|
+
# [File] The local file as Ruby's File class
|
467
|
+
# or
|
468
|
+
# [NilClass] When there's no file, or the file is remotely stored
|
469
|
+
#
|
470
|
+
def to_file
|
471
|
+
return nil unless file.body.is_a? ::File
|
472
|
+
|
473
|
+
if file.body.closed?
|
474
|
+
::File.open(file.body.path) # Reopen if it's already closed
|
475
|
+
else
|
476
|
+
file.body
|
341
477
|
end
|
342
478
|
end
|
343
479
|
|
@@ -362,12 +498,10 @@ module CarrierWave
|
|
362
498
|
# [Fog::#{provider}::Directory] containing directory
|
363
499
|
#
|
364
500
|
def directory
|
365
|
-
@directory ||=
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
)
|
370
|
-
end
|
501
|
+
@directory ||= connection.directories.new(
|
502
|
+
:key => @uploader.fog_directory,
|
503
|
+
:public => @uploader.fog_public
|
504
|
+
)
|
371
505
|
end
|
372
506
|
|
373
507
|
##
|
@@ -381,6 +515,43 @@ module CarrierWave
|
|
381
515
|
@file ||= directory.files.head(path)
|
382
516
|
end
|
383
517
|
|
518
|
+
def copy_options
|
519
|
+
options = {}
|
520
|
+
options.merge!(acl_header) if acl_header.present?
|
521
|
+
options[fog_provider == "Google" ? :content_type : 'Content-Type'] ||= content_type if content_type
|
522
|
+
options.merge(@uploader.fog_attributes)
|
523
|
+
end
|
524
|
+
|
525
|
+
def acl_header
|
526
|
+
case fog_provider
|
527
|
+
when 'AWS'
|
528
|
+
{ 'x-amz-acl' => @uploader.fog_public ? 'public-read' : 'private' }
|
529
|
+
when "Google"
|
530
|
+
@uploader.fog_public ? { destination_predefined_acl: "publicRead" } : {}
|
531
|
+
else
|
532
|
+
{}
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
def fog_provider
|
537
|
+
@uploader.fog_credentials[:provider].to_s
|
538
|
+
end
|
539
|
+
|
540
|
+
def read_source_file
|
541
|
+
source_file = to_file
|
542
|
+
return unless source_file
|
543
|
+
|
544
|
+
begin
|
545
|
+
source_file.read
|
546
|
+
ensure
|
547
|
+
source_file.close
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
551
|
+
def url_options_supported?(local_file)
|
552
|
+
parameters = local_file.method(:url).parameters
|
553
|
+
parameters.count == 2 && parameters[1].include?(:options)
|
554
|
+
end
|
384
555
|
end
|
385
556
|
|
386
557
|
end # Fog
|
data/lib/carrierwave/storage.rb
CHANGED
@@ -1,11 +1,3 @@
|
|
1
1
|
require "carrierwave/storage/abstract"
|
2
2
|
require "carrierwave/storage/file"
|
3
|
-
|
4
|
-
%w(aws google openstack rackspace).each do |fog_dependency|
|
5
|
-
begin
|
6
|
-
require "fog/#{fog_dependency}"
|
7
|
-
rescue LoadError
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
require "carrierwave/storage/fog" if defined?(Fog)
|
3
|
+
require "carrierwave/storage/fog"
|