Определить тип файла в Ruby
Как один надежно определяет тип файла? Анализ расширения файлов неприемлем. Должен быть рубиновый инструмент, похожий на команду UNIX file (1)?
Это относится к типу MIME или типу контента, а не к классификациям файловой системы, таким как каталог, файл или сокет.
Ответы
Ответ 1
Существует привязка ruby к libmagic
, которая делает то, что вам нужно. Он доступен как драгоценный камень с именем ruby-filemagic:
gem install ruby-filemagic
Требовать libmagic-dev
.
Документация кажется немного тонкой, но это должно начать:
$ irb
irb(main):001:0> require 'filemagic'
=> true
irb(main):002:0> fm = FileMagic.new
=> #<FileMagic:0x7fd4afb0>
irb(main):003:0> fm.file('foo.zip')
=> "Zip archive data, at least v2.0 to extract"
irb(main):004:0>
Ответ 2
Если вы используете машину Unix, попробуйте следующее:
mimetype = `file -Ib #{path}`.gsub(/\n/,"")
Я не знаю никаких чистых Ruby-решений, которые надежно работают как "файл".
Отредактировано для добавления: в зависимости от того, какая ОС вы используете, вам может понадобиться использовать "i" вместо "I", чтобы получить файл для возврата типа mime.
Ответ 3
Я считаю, что обстрел будет самым надежным. Для совместимости на Mac OS X и Ubuntu Linux я использовал:
file --mime -b myvideo.mp4
видео /mp 4; кодировка = двоичное
Ubuntu также печатает информацию видеокодека, если это может быть довольно круто:
file -b myvideo.mp4
ISO Media, система MPEG v4, версия 2
Ответ 4
Вы можете использовать эту надежную базу методов в волшебном заголовке файла:
def get_image_extension(local_file_path)
png = Regexp.new("\x89PNG".force_encoding("binary"))
jpg = Regexp.new("\xff\xd8\xff\xe0\x00\x10JFIF".force_encoding("binary"))
jpg2 = Regexp.new("\xff\xd8\xff\xe1(.*){2}Exif".force_encoding("binary"))
case IO.read(local_file_path, 10)
when /^GIF8/
'gif'
when /^#{png}/
'png'
when /^#{jpg}/
'jpg'
when /^#{jpg2}/
'jpg'
else
mime_type = `file #{local_file_path} --mime-type`.gsub("\n", '') # Works on linux and mac
raise UnprocessableEntity, "unknown file type" if !mime_type
mime_type.split(':')[1].split('/')[1].gsub('x-', '').gsub(/jpeg/, 'jpg').gsub(/text/, 'txt').gsub(/x-/, '')
end
end
Ответ 5
Если вы используете класс File, вы можете увеличить его с помощью следующих функций, основанных на ответе @PatrickRichie:
class File
def mime_type
`file --brief --mime-type #{self.path}`.strip
end
def charset
`file --brief --mime #{self.path}`.split(';').second.split('=').second.strip
end
end
И, если вы используете Ruby on Rails, вы можете удалить это в config/initializers/file.rb и получить доступный во всем своем проекте.
Ответ 6
Вы можете дать shared-mime попытку (gem install shared-mime-info). Требуется использование библиотеки share-mime-info Freedesktop, но выполняет как проверки имени файла, так и проверки "волшебства"... попробовал дать ему вихрь сейчас, но у меня нет версии freedesktop shared-mime-info база данных установлена и должна выполнять "настоящую работу", к сожалению, но это может быть то, что вы ищете.
Ответ 7
Недавно я нашел mimetype-fu.
Кажется, это самое простое надежное решение для получения файла MIME-типа.
Единственное предостережение заключается в том, что на компьютере с Windows он использует только расширение файла, тогда как в системах на основе Nix NIX он отлично работает.
Ответ 8
Решение Pure Ruby с использованием магических байтов и возврат символа для соответствующего типа:
https://github.com/SixArm/sixarm_ruby_magic_number_type
Я написал это, поэтому, если у вас есть предложения, дайте мне знать.
Ответ 9
Лучшее, что я нашел до сих пор:
http://bogomips.org/mahoro.git/
Ответ 10
Рубиновый камень хорошо.
mime-types для ruby
Ответ 11
Вы можете дать ссылку MIME:: Типы для Ruby.
Эта библиотека позволяет идентифицировать файлы, вероятно, тип содержимого MIME. Идентификация типа содержимого MIME основана на расширениях файлов.