簡體   English   中英

Ruby檢測上傳文件的MIME類型

[英]Detect MIME type of uploaded file in Ruby

是否有防彈方法來檢測 Ruby 或 Ruby on Rails 中上傳文件的 MIME 類型? 我正在使用 SWFupload 上傳 JPEG 和 PNG, content_type始終是"application/octet-stream"

ruby-filemagic gem 可以做到:

require 'filemagic'

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

這個 gem 根本不看文件擴展名。 它讀取一些文件內容並使用它來猜測文件的類型。

在 Ruby on Rails 中,您可以執行以下操作:

MIME::Types.type_for("filename.gif").first.content_type # => "image/gif"

您可以根據文件的魔術頭使用這種可靠的方法:

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

ruby-filemagic gem 是一個很好的解決方案,但需要額外依賴libmagic (最近作為CarrierWave::MagicMimeTypes刪除的一部分從 CarrierWave 中刪除)。

如果您對純 ruby​​ 實現感興趣,請考慮MimeMagic gem! 它適用於 freedesktop.org mime 數據庫中列出的文件類型:

require 'mimemagic'

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

對於 Microsoft Office 2007+ 格式(xlsx、docx 和 pptx),需要覆蓋(除非您同意這些文件的通用“應用程序/zip”MIME 類型)

require 'mimemagic'    
require 'mimemagic/overlay'

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

filemagic gem 是很好的解決方案,但依賴於許多不必要的 gem。 (rails, aws-sdk-core, ...)

如果您的應用程序很小並且僅在 Linux 或 OSX 中運行,請考慮使用file程序:

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

注意:用任何包含文件路徑的 expr 替換__FILE__

截至 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"

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...

如果您是從頭開始執行此操作,請安裝 mimemagic gem

gem 'mimemagic'

打開流(目標圖像的字節數)

url="https://i.ebayimg.com/images/g/rbIAAOSwojpgyQz1/s-l500.jpg"
result = URI.parse(url).open

然后檢查數據流的文件類型,例如:

MimeMagic.by_magic(result).type == "image/jpeg"

即使如上所述

%w(JPEG GIF TIFF PNG).include?(MimeMagic.by_magic(result).type)

這可能更優雅

你可以使用

Mime::Type.lookup_by_extension(extention_name)

謝謝

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM