Ruby on Rails: как проверить, является ли файл изображением? - PullRequest
17 голосов
/ 08 февраля 2010

Как бы вы проверили, является ли файл изображением? Я думаю, вы могли бы использовать такой метод:

def image?(file)
  file.to_s.include?(".gif") or file.to_s.include?(".png") or file.to_s.include?(".jpg")
end

Но это может быть немного неэффективно и не правильно. Есть идеи?

(я использую плагин paperclip, кстати, но я не вижу никаких способов определить, является ли файл изображением в скрепке)

Ответы [ 6 ]

15 голосов
/ 08 февраля 2010

Я бы использовал гем ruby-filemagic , который является привязкой Ruby для libmagic .

12 голосов
/ 03 декабря 2010

Один из подходов заключается в использовании соглашения о «магическом числе» для чтения первых битов файла.
http://www.astro.keele.ac.uk/oldusers/rno/Computing/File_magic.html

Примеры:

  "BM" is a Bitmap image
  "GIF8" is a GIF image
  "\xff\xd8\xff\xe0" is a JPEG image

Пример в Ruby:

  def bitmap?(data)
    return data[0,2]=="MB"
  end

  def gif?(data)
    return data[0,4]=="GIF8"
  end

  def jpeg?(data)
    return data[0,4]=="\xff\xd8\xff\xe0"
  end

  def file_is_image?(filename)
    f = File.open(filename,'rb')  # rb means to read using binary
    data = f.read(9)              # magic numbers are up to 9 bytes
    f.close
    return bitmap?(data) or gif?(data) or jpeg?(data)
  end

Зачем использовать это вместо расширения имени файла или модуля filemagic?

Для определения типа данных перед записью любых данных на диск. Например, мы можем прочитать поток данных загрузки, прежде чем записывать какие-либо данные на диск. Если магическое число не соответствует типу содержимого веб-формы, мы можем немедленно сообщить об ошибке.

Мы реализуем наш реальный код немного по-другому. Мы создаем хеш: каждый ключ является строкой с магическим числом, каждое значение является символом, подобным: bitmap,: gif,: jpeg и т. Д. Если кто-то захочет увидеть наш реальный код, не стесняйтесь связаться со мной здесь.

11 голосов
/ 13 августа 2015

Пожалуйста, проверьте его один раз

MIME::Types.type_for('tmp/img1.jpg').first.try(:media_type)
=> "image"

MIME::Types.type_for('tmp/img1.jpeg').first.try(:media_type)
=> "image"

MIME::Types.type_for('tmp/img1.gif').first.try(:media_type)
=> "image"

MIME::Types.type_for('tmp/ima1.png').first.try(:media_type)
=> "image"
7 голосов
/ 09 февраля 2010

Поскольку вы используете Paperclip, вы можете использовать встроенный метод validates_attachment_content_type в модели, где используется has_attached_file, и указать, какие типы файлов вы хотите разрешить.

Вот пример из приложения, в котором пользователи загружают аватар для своего профиля:

has_attached_file :avatar, 
                  :styles => { :thumb => "48x48#" },
                  :default_url => "/images/avatars/missing_avatar.png",
                  :default_style => :thumb

validates_attachment_content_type :avatar, :content_type => ["image/jpeg", "image/pjpeg", "image/png", "image/x-png", "image/gif"]

Документация здесь http://dev.thoughtbot.com/paperclip/classes/Paperclip/ClassMethods.html

1 голос
/ 08 февраля 2010

imagemagick имеет команду под названием identity, которая обрабатывает это - проверьте с документацией paperclip - возможно, есть способ справиться с этим из приложения RoR.

0 голосов
/ 14 декабря 2016

Как дополнение к ответу Джоэла, в Rails 5 мне пришлось преобразовать строку сравнения в байт-код. Например:

def jpeg?(data)
  return data[0,4]=="\xff\xd8\xff\xe0".b
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...