【问题标题】:CarrierWave and correct file extension depending on its contentsCarrierWave 和正确的文件扩展名取决于其内容
【发布时间】:2011-09-08 07:33:10
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

    您可以做几件事,具体取决于您是使用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, :...
    

    【讨论】:

    • 走版本路线,如果我想在 N 个版本上更正 M 个扩展怎么办?我需要有 M*N 条件来处理这个吗?
    【解决方案2】:

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

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

    注意:如果图像被仅支持 JPG 和 PNG 图像的 Prawn 使用,这将特别有用。

    上传者类:

    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 类型 (content_type) 更改扩展。

    【讨论】:

      猜你喜欢
      • 2011-01-05
      • 2010-11-21
      • 2012-07-23
      • 1970-01-01
      • 2019-12-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多