CarrierWave и правильное расширение файла в зависимости от его содержимого - PullRequest
4 голосов
/ 08 сентября 2011

Как я могу заставить CarrierWave добавлять правильное расширение к имени файла в зависимости от его содержимого?Например, если я загружаю файл «логотип» (файл PNG без расширения), CarrierWave должен сохранить его как «logo.png».И файл "img.gif" (файл JPG с неверным расширением) соответственно должен быть сохранен как "img.jpg".

Ответы [ 2 ]

4 голосов
/ 23 сентября 2011

Есть несколько вещей, которые вы можете сделать, в зависимости от того, используете ли вы process или version для этого.

Если это версия, то на 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, :...
2 голосов
/ 24 октября 2013

Проблема в том, чтобы определить правильный контент в первую очередь.Carrierwave использует самоцвет MimeType, который определяет его тип mime по расширению.Так как в вашем случае расширение неверно, вам нужен альтернативный способ получения правильного типа MIME.Это лучшее решение, которое мне удалось найти, но оно зависит от способности читать файл изображения с использованием гема RMagick.

Я столкнулся с этой же проблемой и мне пришлось переопределить метод set_content_type по умолчанию длямой загрузчик.Это предполагает, что в вашем Gemfile есть гем Rmagick , так что вы можете получить правильный тип пантомимы при чтении изображения, а не делать лучшие предположения.

Примечание. Это особенно полезно, если 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-типа (content_type).

...