2008-09-09 9 views
65

はファイルの種類をどのようにして決定しますか?ファイル拡張解析は受け入れられません。 UNIXのfile(1)コマンドに似たrubesqueツールが必要ですか?Rubyでファイルタイプを決定する

これは、ディレクトリ、ファイル、またはソケットなどのファイルシステムの分類ではなく、MIMEまたはコンテンツの種類に関するものです。

答えて

-2

MIME::Types for Rubyとすることができます。

このライブラリを使用すると、ファイルのMIMEコンテンツタイプを識別することができます。 MIMEコンテンツタイプの識別は、ファイルのファイル拡張子に基づいています。

+6

Readme.txtより: "MIMEコンテンツタイプの識別は、ファイルのファイル拡張子に基づいています"。 OPは、ファイル名の拡張子ではなく、コンテンツ分析に基づいたメソッドを明示的に要求しました。 –

33

あなたがUnixマシンを使っている場合は、これを試してみてください。

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

私は「ファイル」として確実に機能任意の純粋なRubyのソリューションを認識していませんよ。

追加するように編集:実行中のOSによっては、MIMEタイプを返すファイルを取得するために「私」の代わりに「i」を使用する必要があります。

+16

厄介なハッカーを防ぐために、popen: 'IO.popen([" file "、" --brief "、" --mime-type "、path] in::close、err::close)を使用してみてください。 chomp' – sj26

+0

うん、これやコカイン宝石。 – maletor

+6

@ sj26 'popen'を呼び出すたびに、私はIOオブジェクトが閉じられていないのでゾンビプロセスを取得します。それを修正するには、 'IO.popen([" file "、" --brief "、" --mime-type "、path] in::close、err::close){| io | io.read.chomp} ' – Andrew

2

shared-mimeを試してみてください(gem install shared-mime-info)。 Freedesktopのshared-mime-infoライブラリを使用する必要がありますが、ファイル名/拡張子チェックと「魔法」チェックの両方を行います...今は自分自身で渦を流そうとしましたが、freedesktop共有mime-infoはありませんデータベースはインストールされていて、残念ながら「本物の仕事」をしなければならないが、それはあなたが探しているものかもしれない。

57

あなたが必要とするのはlibmagicへのルビーバインディングです。それはruby-filemagicという名前の宝石として提供されています:

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> 
+0

http://grub.ath.cx/filemagic/CHANGELOGによると、この宝石は積極的に維持されていないようです。 –

+21

この宝石が再び積極的に維持されていることを報告してうれしく思います。https://github.com/blackwinter/ruby-filemagic –

+0

Windowsでも動作します。 –

-1

ルビーの宝石がよくあります。 mime-types for ruby

+0

この宝石は、ファイルの拡張子を使用して、コンテンツではなくタイプを判別します。 –

+0

お返事ありがとうございます。この方法は良い考えではありません。 – Qianjigui

1

私は最近mimetype-fuを見つけました。

ファイルのMIMEタイプを取得するのが最も簡単で信頼できる解決策のようです。

唯一の注意点は、Windowsマシンではファイル拡張子のみを使用しますが、* Nixベースのシステムではうまく動作します。

12

私は、最も信頼できるシェルリングが見つかりました。両方のMac OS XとUbuntu Linuxの互換性のために私が使用:

file --mime -b myvideo.mp4
ビデオ/ MP4を。それができる場合のcharset =バイナリ

Ubuntuのもかなりクールであるビデオコーデックの情報を出力します。

file -b myvideo.mp4
ISOメディア、MPEG v4のシステム、バージョン2

+5

はウェブ利用のために 'file -b --mime-type myvideo.mp4'にする必要があります。 –

8

あなたは、ファイルの魔法のヘッダに、この信頼性の高い方法のベースを使用することができます。

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 
4

あなたは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にドロップして、プロジェクト全体で使用できます。

関連する問題