检测Ruby中上传文件的MIME类型

Vin*_*ent 45 ruby file-upload ruby-on-rails swfupload

是否有一种防弹方法来检测Ruby或Ruby on Rails中上传文件的MIME类型?我使用的SWFUpload上传的JPEG和PNG图像,并content_type始终"application/octet-stream"

Way*_*rad 47

红宝石filemagic创业板将做到这一点:

require 'filemagic'

puts FileMagic.new(FileMagic::MAGIC_MIME).file(__FILE__)
# => text/x-ruby; charset=us-ascii
Run Code Online (Sandbox Code Playgroud)

这个gem根本不会查看文件扩展名.它读取一些文件内容并使用它来猜测文件的类型.

  • 在OS XI上,只需要`brew install libmagic`,之后`gem install ruby​​-filemagic`就可以了.但宝石的作用就像图像/ png,图像/ jpg,应用程序/ x-shockwave-flash,video/mp4,application/ogg,image/vnd.adobe.photoshop,application/pdf,video/x-ms- asf等 (8认同)
  • 如果使用Ubuntu,`apt-get install libmagic-dev`。 (2认同)

NAR*_*KOZ 38

在Ruby on Rails中,您可以:

MIME::Types.type_for("filename.gif").first.content_type # => "image/gif"
Run Code Online (Sandbox Code Playgroud)

  • 不是有效答案,它只是根据其扩展来检测文件类型.如果您命名一个带有FLV扩展名的PNG文件,它会将其检测为=>"video/x-flv" (33认同)
  • 如果您强制执行一致的文件扩展名,那么可能会很好. (9认同)
  • 投票低,因为扩展名与实际文件类型无关.可能根本没有扩展名. (6认同)
  • @IvanBlack这是来自Ruby gem,`mime-types` (6认同)
  • Rails 4.0.1:NameError:未初始化的常量MIME,你的rails版本是什么? (2认同)

Ala*_*ois 21

你可以使用这个可靠的方法基于文件的魔术头:

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
Run Code Online (Sandbox Code Playgroud)

  • 在反引号中运行外部命令时使用字符串插值通常不是一个好主意.`local_file_path`可以设置为`; rm -rf .`.在这种特殊情况下,该方法可以安全地使用`Errno :: ENOENT`失败而不擦除当前目录,但是当文件名由用户提供时,最好不要依赖它. (8认同)

aki*_*kim 16

截至 2021 年,我认为根据所有可用提示(幻数、幻数不够时的文件名、用户提示)计算 mime 类型的最佳工具是Marcel

无耻地引用文档本身:

Marcel::MimeType.for Pathname.new("example.gif")
#  => "image/gif"

File.open "example.gif" do |file|
  Marcel::MimeType.for file
end
#  => "image/gif"

Marcel::MimeType.for Pathname.new("unrecognisable-data"), name: "example.pdf"
#  => "application/pdf"

Marcel::MimeType.for extension: ".pdf"
#  => "application/pdf"

Marcel::MimeType.for Pathname.new("unrecognisable-data"), name: "example", declared_type: "image/png"
#  => "image/png"

Marcel::MimeType.for StringIO.new(File.read "unrecognisable-data")
#  => "application/octet-stream"
Run Code Online (Sandbox Code Playgroud)

  • 检查我的 Gemfile.lock,ActiveStorage 7.0.4.3 依赖于 marcel 和 mini_mime,因此您可以通过使用 Rails 来使用它 (2认同)

Mar*_*arc 12

ruby-filemagic gem是很好的解决方案,但需要对libmagic进行额外的依赖(最近从CarrierWave中移除,作为CarrierWave :: MagicMimeTypes删除的一部分).

如果您对纯ruby实现感兴趣,请考虑MimeMagic gem!它适用于freedesktop.org mime数据库中列出的文件类型:

require 'mimemagic'

MimeMagic.by_magic(File.open('Table-Flip-Guy.jpg')).type # => "image/jpeg" 
Run Code Online (Sandbox Code Playgroud)

对于Microsoft Office 2007+格式(xlsx,docx和pptx),需要覆盖(除非您对这些文件的通用"application/zip"MIME类型没有问题)

require 'mimemagic'    
require 'mimemagic/overlay'

MimeMagic.by_magic(File.open('big_spreadsheet.xlsx')).type # => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" 
Run Code Online (Sandbox Code Playgroud)


kao*_*obo 6

filemagic gem是很好的解决方案,但取决于许多不必要的宝石.(rails,aws-sdk-core,...)

如果您的应用程序很小并且只能在Linux或OSX中运行,请考虑使用file程序:

require 'shellwords'
mimetype = `file --brief --mime-type - < #{Shellwords.shellescape(__FILE__)}`.strip
Run Code Online (Sandbox Code Playgroud)

注意:替换__FILE__为任何expr包含文件路径.


pri*_*iki 5

mimemagic gem 也会这样做

https://github.com/minad/mimemagic

来自官方文档

MimeMagic 是一个通过扩展名或内容来检测文件的 MIME 类型的库。它使用由 freedesktop.org 提供的 mime 数据库(参见http://freedesktop.org/wiki/Software/shared-mime-info/)。

require 'mimemagic'
MimeMagic.by_extension('html').text?
MimeMagic.by_extension('.html').child_of? 'text/plain'
MimeMagic.by_path('filename.txt')
MimeMagic.by_magic(File.open('test.html'))
# etc...
Run Code Online (Sandbox Code Playgroud)