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


193

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

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

基于此假设,除了文件的字节外,您还希望保存MIME类型。

您将如何找到文件的MIME类型?我目前在Mac上,但是在Windows上也应该可以使用。

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

是否有一个整洁的python库来查找此信息?WebService还是(甚至更好的)可下载数据库?

Answers:


217

toivotuo建议的python-magic方法已过时。Python-magic的当前主干位于Github上,并根据该自述文件找到MIME类型,是这样完成的。

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

17
感谢您的评论!请注意,“上”是stackoverflow中的一个困难概念,因为排序是通过投票分组的,并且在组内随机排序。我猜您是指@toivotuo的答案。
达伦·托马斯

1
是的,在撰写此回复时,我没有足够的“要点”来创建评论。但是我可能应该将其写为评论,以便@toivotuo可以编辑他的问题。
西蒙·齐默尔曼

1
rpm -qf /usr/lib/python2.7/site-packages/magic.py -i URL:darwinsys.com/file 摘要:libmagic API的Python绑定rpm -qf / usr / bin / file -i名称:文件网址:darwinsys.com/file 蟒蛇魔法darwinsys.com/file和附带的Linux Fedora的工作方式类似于@ toivotuo的说。而且似乎更主流。
塞尔吉奥

7
请注意,名为python-magic的debian / ubuntu软件包与同名的pip软件包不同。两者都是import magic但内容不兼容。有关更多信息,请参见stackoverflow.com/a/16203777/3189
Hamish Downer 2015年

1
当我评论toivotuo的答案时,它并不落伍!您正在谈论其他图书馆。您能否在回答中删除或替换该声明?当前,这使得找到最佳解决方案真的很困难。
博多

86

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

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


12
如果文件按照问题中的说明存储在BLOB中,则您可能不知道文件扩展名。
机械蜗牛

55
文件扩展名不是确定mime类型的可靠方法。
Cerin 2013年

12
import mimetypes mimetypes.MimeTypes().guess_type(filename)[0]
乔纳森

4
在python 3.6中可以正常工作:mimetypes.guess_type(path_file_to_upload)[1]
JinSnow

3
虽然@cerin是正确的文件扩展名是不可靠的,我刚刚发现的精度python-magic(如在顶部的答案建议)要更低,以证实github.com/s3tools/s3cmd/issues/198。因此,mimetypes对我来说似乎是一个更好的候选人。
丹庆

46

与使用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相匹配。


2
参见Simon Zimmermann的文章,了解python-magic的更新用法
Daren Thomas,2010年

@DarenThomas:正如在mammadori的答案中提到的那样,这个答案并非过时,而且与Simon Zimmermann的解决方案不同。如果安装了文件实用程序,则可能可以使用此解决方案。它适用于我的文件5.32。在gentoo上,还必须为文件包启用python USE-flag。
博多

35

这似乎很容易

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

请参考旧帖子

更新 -根据@Garrets注释,在python 3中更简单:

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

4
我认为您的示例中不需要urllib。
BrotherJack 2014年

5
对于Python 3.X,请使用urllib导入请求替换import urllib。然后使用“请求”代替urllib
Arjun Thakur

1
也适用于python 2.7
Jay Modi

@oetzi的解决方案使用此模块,但更为简单。
加勒特

11

有3种包装libmagic的库。

其中2个在pypi上可用(因此pip安装将起作用):

  • 魔术师
  • 蟒蛇魔术

另外一个与python-magic类似的东西可直接从最新的libmagic来源中获得,它可能是您在Linux发行版中拥有的一个。

在Debian中,python-magic软件包就是关于这一软件包的,它被toivotuo所使用,并且并未像Simon Zimmermann(IMHO)所指出的那样被淘汰。

在我看来,这是另一种观点(由libmagic的原始作者编写)。

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


为了方便起见 ,我添加了一个回购协议:github.com/mammadori/magic-python可以这样: pip install -e git://github.com/mammadori/magic-python.git#egg=Magic_file_extensions
mammadori 2012年

10

在python 2.6中:

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

6
这是不必要的,因为该file命令基本上只是libmagic的包装。您也可以使用Simon答案中的python绑定(python-magic)。
机械蜗牛

6
这取决于操作系统。例如,在Mac OS X上,您具有“文件”,但在正常环境中没有libmagic。
rptb1

9

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'

你能为js或CSS文件做同样的事情吗?
kumbhanibhavesh

当然,为什么不呢?
Gringo Suave

8

Python绑定到libmagic

关于该主题的所有不同答案都非常令人困惑,因此我希望通过对libmagic的不同绑定的概述来更加清楚。以前,mammadori给出了一个简短的答案,列出了可用的选项。

魔力

确定文件mime-type时,简称为选择的工具,file其后端称为libmagic。(请参阅Project主页。)该项目是在私有cvs存储库中开发的,但是github上有一个只读的git mirror

现在,如果您想将任何libmagic绑定与python一起使用,则需要使用此工具,该工具已经附带了自己的python绑定,称为file-magic。它们没有太多专用的文档,但是您可以随时查看c-library的手册页: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使用示例文件中magic.open(flags)所示的创建对象来使用库。

无论toivotuo和ewr2san使用这些file-magic绑定包含在file工具。他们错误地假设,他们正在使用该python-magic程序包。这似乎表明,如果同时安装filepython-magic,则python模块将magic引用前者。

蟒蛇魔术

这是西蒙·齐默尔曼(Simon Zimmermann)在回答中谈到的图书馆,该图书馆也由克劳德·库洛姆贝Claude COULOMBE)和Gringo Suave雇用。

魔术师

注意:该项目的最新更新时间为2013年!

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


7

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

对于压缩文件,它返回:application / gzip; 字符集=二进制

对于未压缩的txt文件(iostat数据):文本/纯文本;字符集= us-ascii

对于tar文件:application / x-tar; 字符集=二进制

对于bz2文件:application / x-bzip2; 字符集=二进制

最后但并非最不重要的一个.zip文件:application / zip; 字符集=二进制


6

您没有说明正在使用的Web服务器,但是Apache有一个很好的小模块,称为Mime Magic,用于告知文件类型,该模块用于确定文件的类型。它读取文件的某些内容,并尝试根据找到的字符找出文件的类型。就像Dave Webb提到的那样,只要有扩展名,python下的MimeTypes模块就可以使用。

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


7
如今,您可以执行subprocess.check_output([''file','-b','--mime',文件名])
Nathan Villaescusa

当python-magic做等效的事情时,实际上没有理由诉诸外部工具,这些东西都包装得很舒适。
13年

6

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

mimetypes.guess_type(url,strict = True)根据文件名或URL(由url给定)猜测文件的类型。返回值是一个元组(类型,编码),如果无法猜测类型(缺少或后缀未知)或类型为'type / subtype'的字符串(可用于MIME内容类型标头),则type为None。

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

可选的strict参数是一个标志,用于指定是否将已知MIME类型的列表限制为仅向IANA注册的正式类型。如果strict为True(默认值),则仅支持IANA类型;否则,不支持。当strict为False时,还将识别一些其他非标准但常用的MIME类型。

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

4

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

会加载整个文件吗?
吴毅凡

不,这是一个流,因此通常只有几个字节。
Claude COULOMBE

我已经通过response.readline()或response.read(128)进行了编辑,谢谢!
Claude COULOMBE

2

我首先尝试mimetypes库。如果不起作用,我改用python-magic libary。

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

1

mimetypes模块仅基于文件扩展名识别文件类型。如果您尝试恢复不带扩展名的文件的文件类型,则mimetypes将不起作用。


3
我认为那不是真的。MIME类型是关于如何告诉其他人有关数据格式的,而不是有关如何自己找出数据格式的。如果您使用的工具仅根据扩展名猜测格式并输出MIME类型,那么如果没有文件扩展名,则无法使用该工具。但是猜测格式的其他方式也是可能的,例如,通过使用解析器进行检查。
erikbwork 2013年

0

我已经尝试了很多示例,但是使用Django 诱变效果很好。

检查文件是否为示例 mp3

from mutagen.mp3 import MP3, HeaderNotFoundError  

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

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


我还需要检查安全性
Artem Bernatskyi


0

对于字节数组类型的数据,可以使用magic.from_buffer(_byte_array,mime = True)


-1

您可以使用imghdr Python模块。


1
这不是有用的评论,因为它没有给出示例,也没有真正说明imghdr在这里将如何或为什么会有所帮助。
erikbwork

1
是的,我知道。已经一年多了,但是也许您仍然可以更新它,因为仍然有像我这样的人在搜索这个问题。如果您需要帮助,可以告诉我。
erikbwork

1
它仅适用于非常有限的图像类型列表。它不知道关于文本文件,压缩归档,文件格式等
tripleee
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.