确定Ruby中的文件类型

确定Ruby中的文件类型,ruby,content-type,mime-types,file-type,Ruby,Content Type,Mime Types,File Type,如何可靠地确定文件的类型?不接受文件扩展名分析。必须有一个类似于UNIX文件(1)命令的rubyesque工具吗 这是关于MIME或内容类型,而不是文件系统分类,如目录、文件或套接字。您可以试试 此库允许识别文件可能的MIME内容类型。MIME内容类型的标识基于文件的文件扩展名 如果您在Unix计算机上,请尝试以下操作: mimetype = `file -Ib #{path}`.gsub(/\n/,"") 我不知道有哪种纯Ruby解决方案能像“文件”一样可靠地工作 编辑添加:根据您正在运行的

如何可靠地确定文件的类型?不接受文件扩展名分析。必须有一个类似于UNIX文件(1)命令的rubyesque工具吗

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

您可以试试

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


如果您在Unix计算机上,请尝试以下操作:

mimetype = `file -Ib #{path}`.gsub(/\n/,"")
我不知道有哪种纯Ruby解决方案能像“文件”一样可靠地工作


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

您可以尝试一下(gem安装共享mime信息)。需要使用Freedesktop共享mime信息库,但同时进行文件名/扩展名检查和“魔法”检查。。。我自己也试过尝试一下,但我没有安装freedesktop共享mime信息数据库,不得不做“真正的工作”,不幸的是,这可能就是你想要的。

有一个ruby绑定到
libmagic
,可以满足你的需要。它可作为名为:

需要
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> 
$irb
irb(主):001:0>需要“filemagic”
=>正确
irb(主):002:0>fm=FileMagic.new
=> #
irb(main):003:0>fm.file('foo.zip')
=>“压缩存档数据,至少要提取v2.0”
irb(主要):004:0>
红宝石很好。 我最近发现了

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


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

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

文件--mime-b myvideo.mp4

视频/mp4;字符集=二进制

Ubuntu还可以打印视频编解码器信息,这很酷:

文件-b myvideo.mp4


ISO媒体,MPEG v4系统,第2版

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


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


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

你可以根据文件的魔法头使用这个可靠的方法:

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

如果您使用的是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的现代方法是使用gem

如果您认为只使用文件扩展名是安全的,那么您可以使用gem:

MIME::Types.type_for('tux.jpg')=>

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

path = # path to your file

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

我可以确认它对我有效。

来自Readme.txt:“MIME内容类型的标识基于文件的文件扩展名”。OP明确请求了一个基于内容分析的方法,而不是文件扩展名。此gem使用文件扩展名来确定类型,而不是内容。根据此gem,它似乎没有被积极维护。我很高兴地报告,此gem再次被积极维护,在Windows上也可以工作。现在,这颗宝石似乎没有得到积极维护。它被标记为“未维护”和“采用我”。为了防止恶意黑客行为,请尝试使用popen:
IO.popen([“文件”、“--short”、“--mime type”,path],in::close,err::close)。read.chomp
是的,这或
可卡因
宝石。@sj26每次调用
popen
,我都会得到一个僵尸进程,因为IO对象没有关闭。要解决这个问题,请使用一个块:
IO.popen([“file”、“--brief”、“--mime type”、path],in::close,err::close){| IO | IO.read.chomp}
@Pete将可能由用户提供的内容插入到命令字符串(如backticks)中是一个潜在的安全漏洞。将popen与参数数组一起使用可防止此类攻击。:-)关于僵尸的精彩观点
IO.popen([“file”、“--brief”、“--mime type”、path]、&:read)。chomp
也可以工作。应该是
file-b--mime type myvideo.mp4
对于web应用,您还需要将“\xff\xd8\xff\xdb”作为JPEG签名。这非常有效,而且不需要添加和维护另一个宝石。
require 'mimemagic'

MimeMagic.by_magic(File.open('tux.jpg')).type # => "image/jpeg" 
MIME::Types.type_for('tux.jpg') => [#<MIME::Type: image/jpeg>]
path = # path to your file

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