PythonでファイルのMIMEタイプを見つけるにはどうすればよいですか?
質問
たとえば、BLOB などのどこかに大量のファイルを保存したいとします。これらのファイルを Web ページ経由で配信し、クライアントが自動的に適切なアプリケーション/ビューアを開くようにしたいとします。
予測:ブラウザは、HTTP 応答の MIME タイプ (コンテンツ タイプ?) ヘッダーによって、どのアプリケーション/ビューアを使用するかを判断します。
その前提に基づいて、ファイルのバイトに加えて、MIME タイプも保存する必要があります。
ファイルの MIME タイプはどうやって調べますか?現在 Mac を使用していますが、これは Windows でも動作するはずです。
ファイルを Web ページに投稿するときに、ブラウザーはこの情報を追加しますか?
この情報を見つけるためのきちんとした Python ライブラリはありますか?WebService ですか、それとも (さらに良い) ダウンロード可能なデータベースですか?
解決
toivotuo によって提案された Python-magic メソッドは時代遅れです。 Python マジック 現在のトランクはGithubにあり、そこにあるreadmeに基づいてMIMEタイプを見つけると、次のようになります。
# For MIME types
>>> import magic
>>> mime = magic.Magic(mime=True)
>>> mime.from_file("testdata/test.pdf")
'application/pdf'
>>>
他のヒント
の MIMEタイプモジュール 標準ライブラリでは、ファイル拡張子から MIME タイプを決定/推測します。
ユーザーがファイルをアップロードしている場合、HTTP ポストにはデータとともにファイルの MIME タイプが含まれます。たとえば、Django はこのデータを アップロードされたファイル 物体。
mimetypes ライブラリを使用するよりも信頼性の高い方法は、python-magic パッケージを使用することです。
import magic
m = magic.open(magic.MAGIC_MIME)
m.load()
m.file("/tmp/document.pdf")
これは file(1) を使用するのと同じです。
Django では、MIME タイプが UploadFile.content_type の MIME タイプと一致することを確認することもできます。
これはとても簡単そうです
>>> from mimetypes import MimeTypes
>>> import urllib
>>> mime = MimeTypes()
>>> url = urllib.pathname2url('Upload.xml')
>>> mime_type = mime.guess_type(url)
>>> print mime_type
('application/xml', None)
ご参照ください 古い投稿
libmagic をラップする 3 つの異なるライブラリがあります。
そのうちの 2 つは pypi で利用できます (したがって、pip install は機能します)。
- ファイルマジック
- Python-マジック
もう 1 つは、python-magic に似たもので、最新の libmagic ソースから直接入手でき、おそらく Linux ディストリビューションに含まれているものです。
Debian では、python-magic パッケージはこれに相当し、toivotuo が言ったように使用されており、Simon Zimmermann が言ったように廃止されていません (私見)。
私には、(libmagic のオリジナルの作者による) 別の解釈のように思えます。
残念ながら pypi では直接利用できません。
Python 2.6では:
mime = subprocess.Popen("/usr/bin/file --mime PATH", shell=True, \
stdout=subprocess.PIPE).communicate()[0]
どの Web サーバーを使用していたかは述べていませんが、Apache には という優れた小さなモジュールがあります。 マイムマジック ファイルのタイプを決定するように指示されたときに、これを使用してファイルのタイプを決定します。ファイルの内容の一部を読み取り、見つかった文字に基づいてファイルのタイプを判断しようとします。そしてとして デイブ・ウェッブの言及 の MimeType モジュール 拡張機能が便利であれば、Python でも動作します。
あるいは、UNIX ボックスを使用している場合は、次のコマンドを使用できます。 sys.popen('file -i ' + fileName, mode='r')
MIME タイプを取得します。Windows には同等のコマンドがあるはずですが、それが何であるかはわかりません。
@toivotuo の方法は、python3 環境で最も効果的かつ最も確実に機能しました。私の目標は、信頼できる .gz 拡張子を持たない gzip 圧縮されたファイルを識別することでした。python3-magicをインストールしました。
import magic
filename = "./datasets/test"
def file_mime_type(filename):
m = magic.open(magic.MAGIC_MIME)
m.load()
return(m.file(filename))
print(file_mime_type(filename))
gzip 圧縮されたファイルの場合は次のように返されます。アプリケーション/gzip;文字セット=バイナリ
解凍された txt ファイル (iostat データ) の場合:テキスト/プレーン;charset=us-ascii
tar ファイルの場合:アプリケーション/x-tar;文字セット=バイナリ
bz2 ファイルの場合:アプリケーション/x-bzip2;文字セット=バイナリ
そして最後に私にとって重要なことは .zip ファイルです。アプリケーション/zip;文字セット=バイナリ
Python 3.x および webapp では、拡張子または偽の拡張子を持たないファイルへの URL が含まれます。次を使用して python-magic をインストールする必要があります。
pip3 install python-magic
Mac OS X の場合は、次のコマンドを使用して libmagic もインストールする必要があります。
brew install libmagic
コードスニペット
import urllib
import magic
from urllib.request import urlopen
url = "http://...url to the file ..."
request = urllib.request.Request(url)
response = urlopen(request)
mime_type = magic.from_buffer(response.readline())
print(mime_type)
あるいは、読み取り値にサイズを入れることもできます
import urllib
import magic
from urllib.request import urlopen
url = "http://...url to the file ..."
request = urllib.request.Request(url)
response = urlopen(request)
mime_type = magic.from_buffer(response.read(128))
print(mime_type)
2017 年の更新
github にアクセスする必要はありません。別の名前で PyPi 上にあります。
pip3 install --user python-magic
# or:
sudo apt install python3-magic # Ubuntu distro package
コードも同様に簡略化できます。
>>> import magic
>>> magic.from_file('/tmp/img_3304.jpg', mime=True)
'image/jpeg'
libmagic への Python バインディング
このトピックに関するさまざまな回答はすべて非常に混乱を招くため、libmagic のさまざまなバインディングの概要を説明することで、もう少し明確にしたいと考えています。以前、マンマドリが与えた 短い答え 利用可能なオプションをリストします。
リブマジック
- モジュール名:
magic
- ピピ: ファイルマジック
- ソース: https://github.com/file/file/tree/master/python
ファイルの MIME タイプを決定する場合、選択したツールは単に呼び出されます。 file
そのバックエンドは次のように呼ばれます libmagic
. 。(「 プロジェクトのホームページ.) プロジェクトはプライベート CVS リポジトリで開発されていますが、 Github 上の読み取り専用 Git ミラー.
このツールは、Python で libmagic バインディングを使用する場合に必要になりますが、すでに という独自の Python バインディングが付属しています。 file-magic
. 。これらに関する専用のドキュメントはあまりありませんが、C ライブラリのマニュアル ページをいつでも見ることができます。 man libmagic
. 。基本的な使い方は、 Readmeファイル:
import magic
detected = magic.detect_from_filename('magic.py')
print 'Detected MIME type: {}'.format(detected.mime_type)
print 'Detected encoding: {}'.format(detected.encoding)
print 'Detected file type name: {}'.format(detected.name)
これとは別に、ライブラリを作成してライブラリを使用することもできます。 Magic
オブジェクトを使用する magic.open(flags)
に示されているように、 サンプルファイル.
両方 トイトゥオ と ewr2san はこれらを使用します file-magic
に含まれるバインディング file
道具。彼らは、 python-magic
パッケージ。 これは、両方の場合、 file
そして python-magic
Python モジュールがインストールされている magic
前者を指します。
Python-マジック
- モジュール名:
magic
- ピピ: Python-マジック
- ソース: https://github.com/ahupp/python-magic
これはサイモン・ツィマーマンが本の中で語っている図書館です。 彼の答え そしてそれはまた採用されています クロード・クーロンブ 同様に グリンゴ・スワーブ.
ファイルマジック
- モジュール名:
magic
- ピピ: ファイルマジック
- ソース: https://github.com/aliles/filemagic
注記:このプロジェクトは 2013 年に最後に更新されました。
同じ c-api に基づいているため、このライブラリは次のライブラリといくつかの類似点があります。 file-magic
に含まれる libmagic
. 。によってのみ言及されています マンマドリ そして他の答えはそれを採用していません。
mimetypes モジュールは、ファイル拡張子に基づいてファイルの種類を認識するだけです。拡張子のないファイルのファイル タイプを回復しようとすると、MIME タイプは機能しません。
多くの例を試しましたが、Django を使用しました 突然変異誘発剤 上手に演奏します。
ファイルが以下であるかどうかを確認する例 mp3
from mutagen.mp3 import MP3, HeaderNotFoundError
try:
audio = MP3(file)
except HeaderNotFoundError:
raise ValidationError('This file should be mp3')
欠点は、ファイルの種類を確認できる機能が制限されていることですが、ファイルの種類を確認するだけでなく、追加情報にもアクセスしたい場合には優れた方法です。
これはすでに古いかもしれませんが、Django から直接、UploadedFile.content_type を使用してみてはいかがでしょうか。同じではない?(https://docs.djangoproject.com/en/1.11/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.content_type)
バイト配列タイプデータの場合、Magic.from_buffer(_byte_array、mime = true)を使用できます。
まずはMIMETYPESライブラリを試してみます。それが機能しない場合は、代わりに python-magic ライブラリを使用します。
import mimetypes
def guess_type(filename, buffer=None):
mimetype, encoding = mimetypes.guess_type(filename)
if mimetype is None:
try:
import magic
if buffer:
mimetype = magic.from_buffer(buffer, mime=True)
else:
mimetype = magic.from_file(filename, mime=True)
except ImportError:
pass
return mimetype
使用できます imghdr Pythonモジュール。