如何可靠地确定文件的类型?文件扩展名分析是不可接受的。一定有类似 UNIX file(1) 命令的 rubyesque 工具吗?
这涉及 MIME 或内容类型,而不是文件系统分类,例如目录、文件或套接字。
有一个与
libmagic
绑定的 ruby 可以满足您的需要。它可以作为名为 ruby-filemagic: 的 gem 提供
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>
如果您使用的是 Unix 机器,请尝试以下操作:
mimetype = `file -Ib #{path}`.gsub(/\n/,"")
我不知道有任何纯 Ruby 解决方案可以像“文件”一样可靠地工作。
编辑添加:根据您运行的操作系统,您可能需要使用“i”而不是“I”来获取文件以返回 mime 类型。
我发现掏钱是最可靠的。为了在 Mac OS X 和 Ubuntu Linux 上兼容,我使用了:
file --mime -b myvideo.mp4
Ubuntu 还可以打印视频编解码器信息(如果可以的话),这非常酷:
file -b myvideo.mp4
您可以根据文件的神奇标头使用这种可靠的方法:
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
这是作为对这个答案的评论添加的,但实际上应该是它自己的答案:
path = # path to your file
IO.popen(
["file", "--brief", "--mime-type", path],
in: :close, err: :close
) { |io| io.read.chomp }
我可以确认它对我有用。
如果您使用的是 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 中,并在整个项目中使用。
对于那些通过搜索引擎来到这里的人来说,在纯 ruby 中查找 MimeType 的现代方法是使用 mimemagic gem。
require 'mimemagic'
MimeMagic.by_magic(File.open('tux.jpg')).type # => "image/jpeg"
如果您认为仅使用文件扩展名是安全的,那么您可以使用 mime-types gem:
MIME::Types.type_for('tux.jpg') => [#<MIME::Type: image/jpeg>]
你可以尝试一下 shared-mime (gem install shared-mime-info)。需要使用 Freedesktop 共享 mime-info 库,但同时进行文件名/扩展名检查以及“魔术”检查...刚才自己尝试了一下,但我没有 freedesktop 共享 mime-info不幸的是,数据库已安装并且必须做“实际工作”,但这可能就是您正在寻找的。
使用魔法字节并返回匹配类型的符号的纯 Ruby 解决方案:
https://github.com/SixArm/sixarm_ruby_magic_number_type
我写的,所以如果你有建议,请告诉我。
我最近发现了mimetype-fu。
这似乎是获取文件 MIME 类型的最简单可靠的解决方案。
唯一需要注意的是,在 Windows 计算机上它仅使用文件扩展名,而在基于 *Nix 的系统上它工作得很好。
迄今为止我发现的最好的:
红宝石很好。 ruby 的 mime 类型
您可以尝试使用 MIME::Types for Ruby。
该库允许识别文件可能的 MIME 内容类型。 MIME 内容类型的识别基于文件的文件扩展名。