如何可靠地确定文件类型?不能使用文件扩展名分析。是否有类似于UNIX file(1)命令的Ruby工具可用?
这涉及MIME或内容类型,而不是文件系统分类,例如目录、文件或套接字。
如何可靠地确定文件类型?不能使用文件扩展名分析。是否有类似于UNIX file(1)命令的Ruby工具可用?
这涉及MIME或内容类型,而不是文件系统分类,例如目录、文件或套接字。
有一个 Ruby 绑定到 libmagic
,可以满足你的需求。它作为一个名为 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 的解决方案能像 'file' 一样可靠地工作。
编辑以添加:根据您运行的操作系统,您可能需要使用 'i' 而不是 'I' 以使文件返回 MIME 类型。
IO.popen(["file", "--brief", "--mime-type", path], in: :close, err: :close).read.chomp
。该命令可用于获取文件的MIME类型,使用时需指定相应的路径。 - sj26cocaine
宝石包。 - maletorpopen
,都会得到一个僵尸进程,因为IO对象没有被关闭。为了解决这个问题,使用一个代码块: IO.popen(["file", "--brief", "--mime-type", path], in: :close, err: :close) { |io| io.read.chomp }
- AndrewIO.popen(["file", "--brief", "--mime-type", path], &:read).chomp
也可以使用。 - sj26我发现使用 shelling out 是最可靠的。为了保证在 Mac OS X 和 Ubuntu Linux 上兼容性,我使用了以下命令:
file --mime -b myvideo.mp4
视频/mp4; 字符集=binary
Ubuntu 还可以打印视频编解码器信息,非常酷:
file -b myvideo.mp4
ISO 媒体,MPEG v4 系统,版本 2
file -b --mime-type myvideo.mp4
来确定视频文件的类型。 - Yam Marcovic根据文件的魔数头,您可以使用这种可靠的方法:
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宝石。
require 'mimemagic'
MimeMagic.by_magic(File.open('tux.jpg')).type # => "image/jpeg"
MIME::Types.type_for('tux.jpg') => [#<MIME::Type: image/jpeg>]
https://github.com/SixArm/sixarm_ruby_magic_number_type
我写了它,如果你有建议,请告诉我。