CarrierWave和正确的文件扩展名取决于其内容

如何根据其内容使CarrierWave添加正确的文件扩展名? 例如,如果我上传文件“logo”(没有扩展名的PNG文件),CarrierWave应将其保存为“logo.png”。 文件“img.gif”(扩展名不正确的JPG文件)应分别保存为“img.jpg”。

您可以执行以下几项操作,具体取决于您是使用process还是version来执行此操作。

如果它是一个版本,那么carrierwave wiki就有办法完成条件版本。 https://github.com/jnicklas/carrierwave/wiki/How-to%3A-Do-conditional-processing

 version :big, :if => :png? do process ... end protected def png?(new_file) new_file.content_type.include? 'png' end 

如果您正在使用process方法,您可能需要查看以下内容: https : //gist.github.com/995663 。

将这些添加到您的代码中以解决该process具有的约束

 # create a new "process_extensions" method. It is like "process", except # it takes an array of extensions as the first parameter, and registers # a trampoline method which checks the extension before invocation def self.process_extensions(*args) extensions = args.shift args.each do |arg| if arg.is_a?(Hash) arg.each do |method, args| processors.push([:process_trampoline, [extensions, method, args]]) end else processors.push([:process_trampoline, [extensions, arg, []]]) end end end # our trampoline method which only performs processing if the extension matches def process_trampoline(extensions, method, args) extension = File.extname(original_filename).downcase extension = extension[1..-1] if extension[0,1] == '.' self.send(method, *args) if extensions.include?(extension) end 

然后,您可以使用它来选择性地在每种文件类型上调用过去的进程

 PNG = %w(png) JPG = %w(jpg jpeg) GIF = %w(gif) def extension_white_list PNG + JPG + GIF end process_extensions PNG, :resize_to_fit => [1024, 768] process_extensions JPG, :... process_extensions GIF, :... 

问题在于首先确定正确的内容。 Carrierwave使用MimeType gem来确定扩展中的mime类型。 因为,在您的情况下,扩展名不正确,您需要另一种方法来获取正确的mime类型。 这是我能够提出的最佳解决方案,但这取决于使用RMagick gem读取图像文件的能力。

我遇到了同样的问题,不得不覆盖我的上传者的默认set_content_type方法。 这假设您在Gemfile中有Rmagick gem,这样您就可以通过读取图像获得正确的mime类型,而不是做出最佳猜测。

注意:如果Prawn正在使用仅支持JPG和PNG图像的图像,则此function特别有用。

上传类:

 process :set_content_type def set_content_type #Note we are overriding the default set_content_type_method for this uploader real_content_type = Magick::Image::read(file.path).first.mime_type if file.respond_to?(:content_type=) file.content_type = real_content_type else file.instance_variable_set(:@content_type, real_content_type) end end 

图像模型:

 class Image < ActiveRecord::Base mount_uploader :image, ImageUploader validates_presence_of :image validate :validate_content_type_correctly before_validation :update_image_attributes private def update_image_attributes if image.present? && image_changed? self.content_type = image.file.content_type end end def validate_content_type_correctly if not ['image/png', 'image/jpg'].include?(content_type) errors.add_to_base "Image format is not a valid JPEG or PNG." return false else return true end end end 

在您的情况下,您可以添加一个基于此正确的mime-type(content_type)更改扩展名的其他方法。