carrierwave-rails3 0.4.5
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.
- data/README.rdoc +527 -0
- data/lib/carrierwave.rb +103 -0
- data/lib/carrierwave/compatibility/paperclip.rb +95 -0
- data/lib/carrierwave/core_ext/file.rb +11 -0
- data/lib/carrierwave/mount.rb +359 -0
- data/lib/carrierwave/orm/activerecord.rb +75 -0
- data/lib/carrierwave/orm/datamapper.rb +27 -0
- data/lib/carrierwave/orm/mongoid.rb +23 -0
- data/lib/carrierwave/orm/mongomapper.rb +27 -0
- data/lib/carrierwave/orm/sequel.rb +45 -0
- data/lib/carrierwave/processing/image_science.rb +116 -0
- data/lib/carrierwave/processing/mini_magick.rb +261 -0
- data/lib/carrierwave/processing/rmagick.rb +278 -0
- data/lib/carrierwave/sanitized_file.rb +273 -0
- data/lib/carrierwave/storage/abstract.rb +30 -0
- data/lib/carrierwave/storage/cloud_files.rb +169 -0
- data/lib/carrierwave/storage/file.rb +48 -0
- data/lib/carrierwave/storage/grid_fs.rb +104 -0
- data/lib/carrierwave/storage/right_s3.rb +3 -0
- data/lib/carrierwave/storage/s3.rb +206 -0
- data/lib/carrierwave/test/matchers.rb +164 -0
- data/lib/carrierwave/uploader.rb +44 -0
- data/lib/carrierwave/uploader/cache.rb +146 -0
- data/lib/carrierwave/uploader/callbacks.rb +41 -0
- data/lib/carrierwave/uploader/configuration.rb +134 -0
- data/lib/carrierwave/uploader/default_url.rb +19 -0
- data/lib/carrierwave/uploader/download.rb +60 -0
- data/lib/carrierwave/uploader/extension_whitelist.rb +38 -0
- data/lib/carrierwave/uploader/mountable.rb +39 -0
- data/lib/carrierwave/uploader/processing.rb +84 -0
- data/lib/carrierwave/uploader/proxy.rb +62 -0
- data/lib/carrierwave/uploader/remove.rb +23 -0
- data/lib/carrierwave/uploader/store.rb +90 -0
- data/lib/carrierwave/uploader/url.rb +33 -0
- data/lib/carrierwave/uploader/versions.rb +147 -0
- data/lib/generators/templates/uploader.rb +47 -0
- data/lib/generators/uploader_generator.rb +13 -0
- data/spec/compatibility/paperclip_spec.rb +52 -0
- data/spec/mount_spec.rb +538 -0
- data/spec/orm/activerecord_spec.rb +271 -0
- data/spec/orm/datamapper_spec.rb +168 -0
- data/spec/orm/mongoid_spec.rb +202 -0
- data/spec/orm/mongomapper_spec.rb +202 -0
- data/spec/orm/sequel_spec.rb +183 -0
- data/spec/processing/image_science_spec.rb +56 -0
- data/spec/processing/mini_magick_spec.rb +76 -0
- data/spec/processing/rmagick_spec.rb +75 -0
- data/spec/sanitized_file_spec.rb +623 -0
- data/spec/spec_helper.rb +92 -0
- data/spec/storage/cloudfiles_spec.rb +78 -0
- data/spec/storage/grid_fs_spec.rb +86 -0
- data/spec/storage/s3_spec.rb +118 -0
- data/spec/uploader/cache_spec.rb +209 -0
- data/spec/uploader/callback_spec.rb +24 -0
- data/spec/uploader/configuration_spec.rb +105 -0
- data/spec/uploader/default_url_spec.rb +85 -0
- data/spec/uploader/download_spec.rb +75 -0
- data/spec/uploader/extension_whitelist_spec.rb +44 -0
- data/spec/uploader/mountable_spec.rb +33 -0
- data/spec/uploader/paths_spec.rb +22 -0
- data/spec/uploader/processing_spec.rb +73 -0
- data/spec/uploader/proxy_spec.rb +54 -0
- data/spec/uploader/remove_spec.rb +70 -0
- data/spec/uploader/store_spec.rb +264 -0
- data/spec/uploader/url_spec.rb +102 -0
- data/spec/uploader/versions_spec.rb +298 -0
- metadata +128 -0
@@ -0,0 +1,278 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
unless defined? Magick
|
4
|
+
begin
|
5
|
+
require 'rmagick'
|
6
|
+
rescue LoadError
|
7
|
+
require 'RMagick'
|
8
|
+
rescue LoadError
|
9
|
+
puts "WARNING: Failed to require rmagick, image processing may fail!"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module CarrierWave
|
14
|
+
|
15
|
+
##
|
16
|
+
# This module simplifies manipulation with RMagick by providing a set
|
17
|
+
# of convenient helper methods. If you want to use them, you'll need to
|
18
|
+
# require this file:
|
19
|
+
#
|
20
|
+
# require 'carrierwave/processing/rmagick'
|
21
|
+
#
|
22
|
+
# And then include it in your uploader:
|
23
|
+
#
|
24
|
+
# class MyUploader < CarrierWave::Uploader::Base
|
25
|
+
# include CarrierWave::RMagick
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# You can now use the provided helpers:
|
29
|
+
#
|
30
|
+
# class MyUploader < CarrierWave::Uploader::Base
|
31
|
+
# include CarrierWave::RMagick
|
32
|
+
#
|
33
|
+
# process :resize_to_fit => [200, 200]
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# Or create your own helpers with the powerful manipulate! method. Check
|
37
|
+
# out the RMagick docs at http://www.imagemagick.org/RMagick/doc/ for more
|
38
|
+
# info
|
39
|
+
#
|
40
|
+
# class MyUploader < CarrierWave::Uploader::Base
|
41
|
+
# include CarrierWave::RMagick
|
42
|
+
#
|
43
|
+
# process :do_stuff => 10.0
|
44
|
+
#
|
45
|
+
# def do_stuff(blur_factor)
|
46
|
+
# manipulate! do |img|
|
47
|
+
# img = img.sepiatone
|
48
|
+
# img = img.auto_orient
|
49
|
+
# img = img.radial_blur(blur_factor)
|
50
|
+
# end
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# === Note
|
55
|
+
#
|
56
|
+
# You should be aware how RMagick handles memory. manipulate! takes care
|
57
|
+
# of freeing up memory for you, but for optimum memory usage you should
|
58
|
+
# use destructive operations as much as possible:
|
59
|
+
#
|
60
|
+
# DON'T DO THIS:
|
61
|
+
# img = img.resize_to_fit
|
62
|
+
#
|
63
|
+
# DO THIS INSTEAD:
|
64
|
+
# img.resize_to_fit!
|
65
|
+
#
|
66
|
+
# Read this for more information why:
|
67
|
+
#
|
68
|
+
# http://rubyforge.org/forum/forum.php?thread_id=1374&forum_id=1618
|
69
|
+
#
|
70
|
+
module RMagick
|
71
|
+
extend ActiveSupport::Concern
|
72
|
+
|
73
|
+
module ClassMethods
|
74
|
+
def convert(format)
|
75
|
+
process :convert => format
|
76
|
+
end
|
77
|
+
|
78
|
+
def resize_to_limit(width, height)
|
79
|
+
process :resize_to_limit => [width, height]
|
80
|
+
end
|
81
|
+
|
82
|
+
def resize_to_fit(width, height)
|
83
|
+
process :resize_to_fit => [width, height]
|
84
|
+
end
|
85
|
+
|
86
|
+
def resize_to_fill(width, height, gravity=::Magick::CenterGravity)
|
87
|
+
process :resize_to_fill => [width, height, gravity]
|
88
|
+
end
|
89
|
+
|
90
|
+
def resize_and_pad(width, height, background=:transparent, gravity=::Magick::CenterGravity)
|
91
|
+
process :resize_and_pad => [width, height, background, gravity]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
##
|
96
|
+
# Changes the image encoding format to the given format
|
97
|
+
#
|
98
|
+
# See even http://www.imagemagick.org/RMagick/doc/magick.html#formats
|
99
|
+
#
|
100
|
+
# === Parameters
|
101
|
+
#
|
102
|
+
# [format (#to_s)] an abreviation of the format
|
103
|
+
#
|
104
|
+
# === Yields
|
105
|
+
#
|
106
|
+
# [Magick::Image] additional manipulations to perform
|
107
|
+
#
|
108
|
+
# === Examples
|
109
|
+
#
|
110
|
+
# image.convert(:png)
|
111
|
+
#
|
112
|
+
def convert(format)
|
113
|
+
manipulate!(:format => format)
|
114
|
+
end
|
115
|
+
|
116
|
+
##
|
117
|
+
# Resize the image to fit within the specified dimensions while retaining
|
118
|
+
# the original aspect ratio. Will only resize the image if it is larger than the
|
119
|
+
# specified dimensions. The resulting image may be shorter or narrower than specified
|
120
|
+
# in the smaller dimension but will not be larger than the specified values.
|
121
|
+
#
|
122
|
+
# === Parameters
|
123
|
+
#
|
124
|
+
# [width (Integer)] the width to scale the image to
|
125
|
+
# [height (Integer)] the height to scale the image to
|
126
|
+
#
|
127
|
+
# === Yields
|
128
|
+
#
|
129
|
+
# [Magick::Image] additional manipulations to perform
|
130
|
+
#
|
131
|
+
def resize_to_limit(width, height)
|
132
|
+
manipulate! do |img|
|
133
|
+
geometry = Magick::Geometry.new(width, height, 0, 0, Magick::GreaterGeometry)
|
134
|
+
new_img = img.change_geometry(geometry) do |new_width, new_height|
|
135
|
+
img.resize(new_width, new_height)
|
136
|
+
end
|
137
|
+
destroy_image(img)
|
138
|
+
new_img = yield(new_img) if block_given?
|
139
|
+
new_img
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
##
|
144
|
+
# From the RMagick documentation: "Resize the image to fit within the
|
145
|
+
# specified dimensions while retaining the original aspect ratio. The
|
146
|
+
# image may be shorter or narrower than specified in the smaller dimension
|
147
|
+
# but will not be larger than the specified values."
|
148
|
+
#
|
149
|
+
# See even http://www.imagemagick.org/RMagick/doc/image3.html#resize_to_fit
|
150
|
+
#
|
151
|
+
# === Parameters
|
152
|
+
#
|
153
|
+
# [width (Integer)] the width to scale the image to
|
154
|
+
# [height (Integer)] the height to scale the image to
|
155
|
+
#
|
156
|
+
# === Yields
|
157
|
+
#
|
158
|
+
# [Magick::Image] additional manipulations to perform
|
159
|
+
#
|
160
|
+
def resize_to_fit(width, height)
|
161
|
+
manipulate! do |img|
|
162
|
+
img.resize_to_fit!(width, height)
|
163
|
+
img = yield(img) if block_given?
|
164
|
+
img
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
##
|
169
|
+
# From the RMagick documentation: "Resize the image to fit within the
|
170
|
+
# specified dimensions while retaining the aspect ratio of the original
|
171
|
+
# image. If necessary, crop the image in the larger dimension."
|
172
|
+
#
|
173
|
+
# See even http://www.imagemagick.org/RMagick/doc/image3.html#resize_to_fill
|
174
|
+
#
|
175
|
+
# === Parameters
|
176
|
+
#
|
177
|
+
# [width (Integer)] the width to scale the image to
|
178
|
+
# [height (Integer)] the height to scale the image to
|
179
|
+
#
|
180
|
+
# === Yields
|
181
|
+
#
|
182
|
+
# [Magick::Image] additional manipulations to perform
|
183
|
+
#
|
184
|
+
def resize_to_fill(width, height, gravity=::Magick::CenterGravity)
|
185
|
+
manipulate! do |img|
|
186
|
+
img.crop_resized!(width, height, gravity)
|
187
|
+
img = yield(img) if block_given?
|
188
|
+
img
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
##
|
193
|
+
# Resize the image to fit within the specified dimensions while retaining
|
194
|
+
# the original aspect ratio. If necessary, will pad the remaining area
|
195
|
+
# with the given color, which defaults to transparent (for gif and png,
|
196
|
+
# white for jpeg).
|
197
|
+
#
|
198
|
+
# === Parameters
|
199
|
+
#
|
200
|
+
# [width (Integer)] the width to scale the image to
|
201
|
+
# [height (Integer)] the height to scale the image to
|
202
|
+
# [background (String, :transparent)] the color of the background as a hexcode, like "#ff45de"
|
203
|
+
# [gravity (Magick::GravityType)] how to position the image
|
204
|
+
#
|
205
|
+
# === Yields
|
206
|
+
#
|
207
|
+
# [Magick::Image] additional manipulations to perform
|
208
|
+
#
|
209
|
+
def resize_and_pad(width, height, background=:transparent, gravity=::Magick::CenterGravity)
|
210
|
+
manipulate! do |img|
|
211
|
+
img.resize_to_fit!(width, height)
|
212
|
+
new_img = ::Magick::Image.new(width, height)
|
213
|
+
if background == :transparent
|
214
|
+
filled = new_img.matte_floodfill(1, 1)
|
215
|
+
else
|
216
|
+
filled = new_img.color_floodfill(1, 1, ::Magick::Pixel.from_color(background))
|
217
|
+
end
|
218
|
+
destroy_image(new_img)
|
219
|
+
filled.composite!(img, gravity, ::Magick::OverCompositeOp)
|
220
|
+
destroy_image(img)
|
221
|
+
filled = yield(filled) if block_given?
|
222
|
+
filled
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
##
|
227
|
+
# Manipulate the image with RMagick. This method will load up an image
|
228
|
+
# and then pass each of its frames to the supplied block. It will then
|
229
|
+
# save the image to disk.
|
230
|
+
#
|
231
|
+
# === Gotcha
|
232
|
+
#
|
233
|
+
# This method assumes that the object responds to +current_path+.
|
234
|
+
# Any class that this module is mixed into must have a +current_path+ method.
|
235
|
+
# CarrierWave::Uploader does, so you won't need to worry about this in
|
236
|
+
# most cases.
|
237
|
+
#
|
238
|
+
# === Yields
|
239
|
+
#
|
240
|
+
# [Magick::Image] manipulations to perform
|
241
|
+
#
|
242
|
+
# === Raises
|
243
|
+
#
|
244
|
+
# [CarrierWave::ProcessingError] if manipulation failed.
|
245
|
+
#
|
246
|
+
def manipulate!(options={})
|
247
|
+
image = ::Magick::Image.read(current_path)
|
248
|
+
|
249
|
+
frames = if image.size > 1
|
250
|
+
list = ::Magick::ImageList.new
|
251
|
+
image.each do |frame|
|
252
|
+
list << yield( frame )
|
253
|
+
end
|
254
|
+
list
|
255
|
+
else
|
256
|
+
frame = image.first
|
257
|
+
frame = yield( frame ) if block_given?
|
258
|
+
frame
|
259
|
+
end
|
260
|
+
|
261
|
+
if options[:format]
|
262
|
+
frames.write("#{options[:format]}:#{current_path}")
|
263
|
+
else
|
264
|
+
frames.write(current_path)
|
265
|
+
end
|
266
|
+
destroy_image(frames)
|
267
|
+
rescue ::Magick::ImageMagickError => e
|
268
|
+
raise CarrierWave::ProcessingError.new("Failed to manipulate with rmagick, maybe it is not an image? Original Error: #{e}")
|
269
|
+
end
|
270
|
+
|
271
|
+
private
|
272
|
+
|
273
|
+
def destroy_image(image)
|
274
|
+
image.destroy! if image.respond_to?(:destroy!)
|
275
|
+
end
|
276
|
+
|
277
|
+
end # RMagick
|
278
|
+
end # CarrierWave
|
@@ -0,0 +1,273 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
module CarrierWave
|
6
|
+
|
7
|
+
##
|
8
|
+
# SanitizedFile is a base class which provides a common API around all
|
9
|
+
# the different quirky Ruby File libraries. It has support for Tempfile,
|
10
|
+
# File, StringIO, Merb-style upload Hashes, as well as paths given as
|
11
|
+
# Strings and Pathnames.
|
12
|
+
#
|
13
|
+
# It's probably needlessly comprehensive and complex. Help is appreciated.
|
14
|
+
#
|
15
|
+
class SanitizedFile
|
16
|
+
|
17
|
+
attr_accessor :file
|
18
|
+
|
19
|
+
def initialize(file)
|
20
|
+
self.file = file
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Returns the filename as is, without sanizting it.
|
25
|
+
#
|
26
|
+
# === Returns
|
27
|
+
#
|
28
|
+
# [String] the unsanitized filename
|
29
|
+
#
|
30
|
+
def original_filename
|
31
|
+
return @original_filename if @original_filename
|
32
|
+
if @file and @file.respond_to?(:original_filename)
|
33
|
+
@file.original_filename
|
34
|
+
elsif path
|
35
|
+
File.basename(path)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# Returns the filename, sanitized to strip out any evil characters.
|
41
|
+
#
|
42
|
+
# === Returns
|
43
|
+
#
|
44
|
+
# [String] the sanitized filename
|
45
|
+
#
|
46
|
+
def filename
|
47
|
+
sanitize(original_filename) if original_filename
|
48
|
+
end
|
49
|
+
|
50
|
+
alias_method :identifier, :filename
|
51
|
+
|
52
|
+
##
|
53
|
+
# Returns the part of the filename before the extension. So if a file is called 'test.jpeg'
|
54
|
+
# this would return 'test'
|
55
|
+
#
|
56
|
+
# === Returns
|
57
|
+
#
|
58
|
+
# [String] the first part of the filename
|
59
|
+
#
|
60
|
+
def basename
|
61
|
+
split_extension(filename)[0] if filename
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Returns the file extension
|
66
|
+
#
|
67
|
+
# === Returns
|
68
|
+
#
|
69
|
+
# [String] the extension
|
70
|
+
#
|
71
|
+
def extension
|
72
|
+
split_extension(filename)[1] if filename
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# Returns the file's size.
|
77
|
+
#
|
78
|
+
# === Returns
|
79
|
+
#
|
80
|
+
# [Integer] the file's size in bytes.
|
81
|
+
#
|
82
|
+
def size
|
83
|
+
if is_path?
|
84
|
+
exists? ? File.size(path) : 0
|
85
|
+
elsif @file.respond_to?(:size)
|
86
|
+
@file.size
|
87
|
+
elsif path
|
88
|
+
exists? ? File.size(path) : 0
|
89
|
+
else
|
90
|
+
0
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
##
|
95
|
+
# Returns the full path to the file. If the file has no path, it will return nil.
|
96
|
+
#
|
97
|
+
# === Returns
|
98
|
+
#
|
99
|
+
# [String, nil] the path where the file is located.
|
100
|
+
#
|
101
|
+
def path
|
102
|
+
unless @file.blank?
|
103
|
+
if is_path?
|
104
|
+
File.expand_path(@file)
|
105
|
+
elsif @file.respond_to?(:path) and not @file.path.blank?
|
106
|
+
File.expand_path(@file.path)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
##
|
112
|
+
# === Returns
|
113
|
+
#
|
114
|
+
# [Boolean] whether the file is supplied as a pathname or string.
|
115
|
+
#
|
116
|
+
def is_path?
|
117
|
+
!!((@file.is_a?(String) || @file.is_a?(Pathname)) && !@file.blank?)
|
118
|
+
end
|
119
|
+
|
120
|
+
##
|
121
|
+
# === Returns
|
122
|
+
#
|
123
|
+
# [Boolean] whether the file is valid and has a non-zero size
|
124
|
+
#
|
125
|
+
def empty?
|
126
|
+
@file.nil? || self.size.nil? || self.size.zero?
|
127
|
+
end
|
128
|
+
|
129
|
+
alias_method :blank?, :empty?
|
130
|
+
|
131
|
+
##
|
132
|
+
# === Returns
|
133
|
+
#
|
134
|
+
# [Boolean] Whether the file exists
|
135
|
+
#
|
136
|
+
def exists?
|
137
|
+
return File.exists?(self.path) if self.path
|
138
|
+
return false
|
139
|
+
end
|
140
|
+
|
141
|
+
##
|
142
|
+
# Returns the contents of the file.
|
143
|
+
#
|
144
|
+
# === Returns
|
145
|
+
#
|
146
|
+
# [String] contents of the file
|
147
|
+
#
|
148
|
+
def read
|
149
|
+
if is_path?
|
150
|
+
File.open(@file, "rb").read
|
151
|
+
else
|
152
|
+
@file.rewind if @file.respond_to?(:rewind)
|
153
|
+
@file.read
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
##
|
158
|
+
# Moves the file to the given path
|
159
|
+
#
|
160
|
+
# === Parameters
|
161
|
+
#
|
162
|
+
# [new_path (String)] The path where the file should be moved.
|
163
|
+
# [permissions (Integer)] permissions to set on the file in its new location.
|
164
|
+
#
|
165
|
+
def move_to(new_path, permissions=nil)
|
166
|
+
return if self.empty?
|
167
|
+
new_path = File.expand_path(new_path)
|
168
|
+
|
169
|
+
mkdir!(new_path)
|
170
|
+
if exists?
|
171
|
+
FileUtils.mv(path, new_path) unless new_path == path
|
172
|
+
else
|
173
|
+
File.open(new_path, "wb") { |f| f.write(read) }
|
174
|
+
end
|
175
|
+
chmod!(new_path, permissions)
|
176
|
+
self.file = new_path
|
177
|
+
end
|
178
|
+
|
179
|
+
##
|
180
|
+
# Creates a copy of this file and moves it to the given path. Returns the copy.
|
181
|
+
#
|
182
|
+
# === Parameters
|
183
|
+
#
|
184
|
+
# [new_path (String)] The path where the file should be copied to.
|
185
|
+
# [permissions (Integer)] permissions to set on the copy
|
186
|
+
#
|
187
|
+
# === Returns
|
188
|
+
#
|
189
|
+
# @return [CarrierWave::SanitizedFile] the location where the file will be stored.
|
190
|
+
#
|
191
|
+
def copy_to(new_path, permissions=nil)
|
192
|
+
return if self.empty?
|
193
|
+
new_path = File.expand_path(new_path)
|
194
|
+
|
195
|
+
mkdir!(new_path)
|
196
|
+
if exists?
|
197
|
+
FileUtils.cp(path, new_path) unless new_path == path
|
198
|
+
else
|
199
|
+
File.open(new_path, "wb") { |f| f.write(read) }
|
200
|
+
end
|
201
|
+
chmod!(new_path, permissions)
|
202
|
+
self.class.new(new_path)
|
203
|
+
end
|
204
|
+
|
205
|
+
##
|
206
|
+
# Removes the file from the filesystem.
|
207
|
+
#
|
208
|
+
def delete
|
209
|
+
FileUtils.rm(self.path) if exists?
|
210
|
+
end
|
211
|
+
|
212
|
+
##
|
213
|
+
# Returns the content type of the file.
|
214
|
+
#
|
215
|
+
# === Returns
|
216
|
+
#
|
217
|
+
# [String] the content type of the file
|
218
|
+
#
|
219
|
+
def content_type
|
220
|
+
return @content_type if @content_type
|
221
|
+
@file.content_type.chomp if @file.respond_to?(:content_type) and @file.content_type
|
222
|
+
end
|
223
|
+
|
224
|
+
private
|
225
|
+
|
226
|
+
def file=(file)
|
227
|
+
if file.is_a?(Hash)
|
228
|
+
@file = file["tempfile"] || file[:tempfile]
|
229
|
+
@original_filename = file["filename"] || file[:filename]
|
230
|
+
@content_type = file["content_type"] || file[:content_type]
|
231
|
+
else
|
232
|
+
@file = file
|
233
|
+
@original_filename = nil
|
234
|
+
@content_type = nil
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# create the directory if it doesn't exist
|
239
|
+
def mkdir!(path)
|
240
|
+
FileUtils.mkdir_p(File.dirname(path)) unless File.exists?(File.dirname(path))
|
241
|
+
end
|
242
|
+
|
243
|
+
def chmod!(path, permissions)
|
244
|
+
File.chmod(permissions, path) if permissions
|
245
|
+
end
|
246
|
+
|
247
|
+
# Sanitize the filename, to prevent hacking
|
248
|
+
def sanitize(name)
|
249
|
+
name = name.gsub("\\", "/") # work-around for IE
|
250
|
+
name = File.basename(name)
|
251
|
+
name = name.gsub(/[^a-zA-Z0-9\.\-\+_]/,"_")
|
252
|
+
name = "_#{name}" if name =~ /\A\.+\z/
|
253
|
+
name = "unnamed" if name.size == 0
|
254
|
+
return name.downcase
|
255
|
+
end
|
256
|
+
|
257
|
+
def split_extension(filename)
|
258
|
+
# regular expressions to try for identifying extensions
|
259
|
+
extension_matchers = [
|
260
|
+
/\A(.+)\.(tar\.gz)\z/, # matches "something.tar.gz"
|
261
|
+
/\A(.+)\.([^\.]+)\z/ # matches "something.jpg"
|
262
|
+
]
|
263
|
+
|
264
|
+
extension_matchers.each do |regexp|
|
265
|
+
if filename =~ regexp
|
266
|
+
return $1, $2
|
267
|
+
end
|
268
|
+
end
|
269
|
+
return filename, "" # In case we weren't able to split the extension
|
270
|
+
end
|
271
|
+
|
272
|
+
end # SanitizedFile
|
273
|
+
end # CarrierWave
|