78

如何可靠地确定文件的类型?文件扩展名分析是不可接受的。一定有类似于 UNIX file(1) 命令的 ruby​​esque 工具?

这是关于 MIME 或内容类型,而不是文件系统分类,例如目录、文件或套接字。

4

13 回答 13

58

有一个红宝石绑定可以满足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> 
于 2009-05-23T14:52:32.480 回答
35

如果你在 Unix 机器上试试这个:

mimetype = `file -Ib #{path}`.gsub(/\n/,"")

我不知道有任何纯 Ruby 解决方案可以像“文件”一样可靠地工作。

编辑添加:根据您运行的操作系统,您可能需要使用“i”而不是“I”来获取文件以返回 mime 类型。

于 2008-09-11T15:41:08.193 回答
14

我发现炮击是最可靠的。为了在 Mac OS X 和 Ubuntu Linux 上兼容,我使用了:

file --mime -b myvideo.mp4
视频/mp4;字符集=二进制

如果可以的话,Ubuntu 还会打印视频编解码器信息,这非常酷:

file -b myvideo.mp4
ISO 媒体,MPEG v4 系统,版本 2

于 2010-11-07T09:20:35.803 回答
10

您可以根据文件的魔术头使用这种可靠的方法:

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
于 2013-05-19T14:57:48.660 回答
10

这是作为对此答案的评论添加的,但实际上应该是它自己的答案:

path = # path to your file

IO.popen(
  ["file", "--brief", "--mime-type", path],
  in: :close, err: :close
) { |io| io.read.chomp }

我可以确认它对我有用。

于 2019-08-09T14:14:03.843 回答
7

如果您使用的是 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 并在整个项目中使用。

于 2014-09-17T14:04:24.440 回答
3

对于那些通过搜索引擎来到这里的人来说,在纯 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>]
于 2018-05-10T17:05:17.737 回答
2

你可以试试shared-mime (gem install shared-mime-info)。需要使用 Freedesktop shared-mime-info 库,但同时进行文件名/扩展名检查以及“魔术”检查...我自己试了一下,但我没有 freedesktop shared-mime-info不幸的是,数据库已安装并且必须做“真正的工作”,但这可能是您正在寻找的。

于 2008-09-18T16:21:08.740 回答
1

使用魔术字节并返回匹配类型的符号的纯 Ruby 解决方案:

https://github.com/SixArm/sixarm_ruby_magic_number_type

我写的,所以如果你有建议,请告诉我。

于 2012-04-20T20:35:51.057 回答
1

我最近发现了mimetype-fu

获取文件的 MIME 类型似乎是最简单可靠的解决方案。

唯一需要注意的是,在 Windows 机器上它只使用文件扩展名,而在基于 *Nix 的系统上它工作得很好。

于 2010-09-20T17:51:53.523 回答
0

到目前为止我发现的最好的:

http://bogomips.org/mahoro.git/

于 2012-01-25T16:02:40.327 回答
-1

红宝石很好。 ruby 的 mime 类型

于 2009-09-03T14:24:07.073 回答
-3

你可以试试MIME::Types for Ruby

该库允许识别文件可能的 MIME 内容类型。MIME 内容类型的标识基于文件的文件扩展名。

于 2008-09-09T11:10:42.340 回答