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

时间:2011-09-08 07:33:11

标签: ruby-on-rails ruby ruby-on-rails-3 rmagick carrierwave

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

2 个答案:

答案 0 :(得分:4)

您可以执行以下几项操作,具体取决于您是使用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, :...

答案 1 :(得分:2)

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

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

注意:如果Prawn正在使用仅支持JPG和PNG图像的图像,这将非常有用。

上传者类:

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)更改扩展名的其他方法。