如何在python中找到文件的mime类型?

假设您想要在某个地方保存一堆文件,例如在blob中。假设您希望通过网页分发这些文件,并让客户端自动打开正确的应用程序/查看器。

假设:浏览器通过HTTP响应中的mime-type (content-type?)报头确定要使用哪个应用程序/查看器。

基于这个假设,除了文件的字节外,还需要保存MIME类型。

如何找到文件的MIME类型?我现在用的是Mac,但这应该也适用于Windows。

浏览器是否在将文件发布到网页时添加此信息?

是否有一个简洁的python库来查找这些信息?WebService还是(更好的)一个可下载的数据库?

251141 次浏览

标准库中的mimetype模块将根据文件扩展名确定/猜测MIME类型。

如果用户正在上传文件,HTTP post将在数据旁边包含文件的MIME类型。例如,Django将此数据作为UploadedFile对象的属性提供。

你没有说明你使用的是什么web服务器,但是Apache有一个叫做Mime魔法的小模块,当被告知这样做时,它用来确定文件的类型。它读取文件的一些内容,并试图根据找到的字符找出文件的类型。并且作为Dave Webb, python下的mimetype模块将工作,只要扩展是方便的。

或者,如果你坐在UNIX机器上,你可以使用sys.popen('file -i ' + fileName, mode='r')来获取MIME类型。Windows应该有一个等效的命令,但我不确定它是什么。

在python 2.6中:

import shlex
import subprocess
mime = subprocess.Popen("/usr/bin/file --mime " + shlex.quote(PATH), shell=True, \
stdout=subprocess.PIPE).communicate()[0]

比使用mimetypes库更可靠的方法是使用python-magic包。

import magic
m = magic.open(magic.MAGIC_MIME)
m.load()
m.file("/tmp/document.pdf")

这相当于使用file(1)。

在Django中,还可以确保MIME类型与UploadedFile.content_type匹配。

toivotuo建议的python-magic方法已经过时。Python-magic的当前的中继在Github,基于那里的自述me,找到mime类型,是这样做的。

# For MIME types
import magic
mime = magic.Magic(mime=True)
mime.from_file("testdata/test.pdf") # 'application/pdf'

mimetypes模块只是基于文件扩展名来识别文件类型。如果尝试恢复没有扩展名的文件的文件类型,mimetypes将不起作用。

有3个不同的库包装libmagic。

其中2个在pypi上可用(所以PIP安装可以工作):

  • filemagic
  • python-magic

另一种类似于python-magic的方法可以在最新的libmagic源代码中直接获得,它可能是您的linux发行版中所拥有的。

在Debian中,python-magic包就是这样的,它像toivotuo说的那样被使用,它并没有像Simon Zimmermann说的那样被淘汰(IMHO)。

在我看来,这是另一种说法(出自《libmagic》的原作者)。

太糟糕了,pypi上不能直接使用。

这似乎很简单

>>> 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)

请参考旧邮政

更新 -在python 3+版本中,现在更方便:

import mimetypes
print(mimetypes.guess_type("sample.html"))

@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;charset =二进制< / p >

解压缩TXT文件(iostat数据): 文本/平原;charset = us - ascii < / p >

tar文件: 应用程序/ x-tar;charset =二进制< / p >

对于bz2文件: 应用程序/ x-bzip2;charset =二进制< / p >

和最后一个但并非最不重要的。zip文件: 应用程序/邮政编码;charset =二进制< / p >

在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)

或者,您可以在read中输入一个大小

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)

我已经尝试了很多例子,但与Django 诱变剂发挥得很好。

检查files是否为mp3的例子

from mutagen.mp3 import MP3, HeaderNotFoundError


try:
audio = MP3(file)
except HeaderNotFoundError:
raise ValidationError('This file should be mp3')

缺点是你检查文件类型的能力是有限的,但如果你不仅想检查文件类型,而且还想访问其他信息,这是一个很好的方法。

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的不同绑定来更清楚地说明问题。以前mammadori给出了一个简短的回答列表可用的选项。

libmagic

在确定文件mime类型时,所选择的工具简单地称为file,其后端称为libmagic。(参见项目首页。)该项目是在私有cvs存储库中开发的,但是有只读git镜像在github上

现在,如果你想在python中使用任何libmagic绑定,你将需要这个工具,它已经自带名为file-magic的python绑定。关于它们没有太多专门的文档,但你总是可以看看c库的手册页:man libmagic。基本用法在自述文件中描述:

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.open(flags)创建一个Magic对象来使用这个库,如示例文件. xml中所示。

toivotuo和ewr2san都使用file工具中包含的这些file-magic绑定。他们错误地假设,他们正在使用python-magic包。这似乎表明,如果同时安装了__ABC1和__ABC2,则python模块magic指向前者。

python-magic

这是Simon Zimmermann在他的回答中谈到的库,也被克劳德COULOMBE外国佬的温文尔雅使用。

filemagic

请注意:该项目最后一次更新在2013年!

由于基于相同的c-api,这个库与libmagic中包含的file-magic有一些相似之处。它只被mammadori提到,没有其他答案使用它。

For byte可以使用的数组类型数据 magic.from_buffer (_byte_array mime = True) < / p >

我首先尝试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

python 3 ref: https://docs.python.org/3.2/library/mimetypes.html

< p > mimetype。guess_type(url, strict=True)基于猜测文件的类型 在它的文件名或URL上,由URL给出。返回值是一个元组 (type, encoding),如果无法猜出类型,则type为None (缺少或未知后缀)或'type/subtype'形式的字符串,

encoding为None表示没有编码或用于该编码的程序的名称 编码(例如压缩或gzip)。该编码适合用作 Content-Encoding头,而不是Content-Transfer-Encoding头。 映射是表驱动的。编码后缀区分大小写; 类型后缀首先是区分大小写的,然后是大小写 如果不。< / p >

可选的strict参数是一个标志,指定的列表是否 已知的MIME类型仅限于注册的正式类型 IANA。当strict为True(默认值)时,只有IANA类型是True 支持;当strict为False时,一些附加的非标准but 通常使用的MIME类型也可以识别

import mimetypes
print(mimetypes.guess_type("sample.html"))

我很惊讶没有人提到它,但是Pygments能够对mime类型做出有根据的猜测,特别是文本文档。

pyements实际上是一个Python语法高亮显示库,但它有一个方法,可以对您的文档是500种受支持的文档类型中的哪一种进行有根据的猜测。 即c++ vs c# vs Python vs etc

import inspect


def _test(text: str):
from pygments.lexers import guess_lexer
lexer = guess_lexer(text)
mimetype = lexer.mimetypes[0] if lexer.mimetypes else None
print(mimetype)


if __name__ == "__main__":
# Set the text to the actual defintion of _test(...) above
text = inspect.getsource(_test)
print('Text:')
print(text)
print()
print('Result:')
_test(text)

输出:

Text:
def _test(text: str):
from pygments.lexers import guess_lexer
lexer = guess_lexer(text)
mimetype = lexer.mimetypes[0] if lexer.mimetypes else None
print(mimetype)




Result:
text/x-python

现在,它不是完美的,但如果您需要能够分辨出500种文档格式中正在使用的是哪一种,这是非常有用的。

13年后…
本页上关于python3的大多数答案不是过时就是不完整。
要获得文件的mime类型,我使用:

import mimetypes


mt = mimetypes.guess_type("https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf")
if mt:
print("Mime Type:", mt[0])
else:
print("Cannot determine Mime Type")


# Mime Type: application/pdf

< a href = " https://trinket。io/python3/1485835cd1" rel="noreferrer">Live Demo . io/python3/1485835cd1" rel="noreferrer">Live Demo


Python文档:

mimetypes.guess_type (url 严格= True)

根据url给出的文件名、路径或URL猜测文件的类型。URL可以是字符串或就对象

返回值是一个元组(type, encoding),如果类型无法猜到(缺少或未知后缀),则类型None;或者是一个形式为'type/subtype'的字符串,可用于MIME 内容类型标头。

编码None,表示没有编码或用于编码的程序的名称(例如压缩gzip)。该编码适合用作内容编码标头,用作Content-Transfer-Encoding标头。映射是表驱动的。编码后缀区分大小写;类型后缀首先区分大小写,然后不区分大小写。

可选参数严格的是一个标志,指定已知MIME类型列表是否仅限于正式类型在IANA注册。当严格的True(默认值)时,只支持IANA类型;当严格的False时,一些额外的非标准但常用的MIME类型也会被识别出来。

在3.8版更改:增加了对url为就对象的支持。