236

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

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

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

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

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

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

4

18 回答 18

264

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'
于 2010-05-02T12:02:45.380 回答
111

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

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

于 2008-09-04T12:12:20.690 回答
51

比使用 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 的匹配。

于 2010-01-25T16:39:06.130 回答
45

这似乎很容易

>>> 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"))
于 2014-02-13T13:09:49.320 回答
15

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'
于 2017-10-15T19:09:35.613 回答
15

Python 绑定到 libmagic

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

libmagic

在确定文件的 mime 类型时,只需调用选择的工具,并调用file其后端libmagic。(参见项目主页。)该项目是在私有 cvs-repository 中开发的,但在 github 上有一个只读的 git 镜像

现在,如果您想将任何 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 COULOMBEGringo Suave使用的图书馆。

文件魔术

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

由于基于相同的 c-api,该库与file-magic包含在libmagic. 它仅被mammadori提及,没有其他答案使用它。

于 2018-06-22T10:25:39.930 回答
13

13 年后...
此页面上有关 python 3 的大多数答案要么已过时,要么不完整。
要获得我使用的 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

现场演示


来自Python 文档

mimetypes.guess_type网址严格=真

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

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

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

可选的strict参数是一个标志,指定已知 MIME 类型的列表是否仅限于在IANA 注册的官方类型。当strictTrue(默认)时,仅支持 IANA 类型;当strict is时False,还会识别一些额外的非标准但常用的 MIME 类型。

在 3.8 版更改: 添加了对 url 作为类路径对象的支持。

于 2021-02-02T15:08:42.120 回答
11

有 3 个不同的库包装了 libmagic。

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

  • 文件魔术
  • 蟒蛇魔术

另一个类似于 python-magic 的,可以直接在最新的 libmagic 源中获得,它可能是你的 linux 发行版中的那个。

在 Debian 中,python-magic 包是关于这个的,它像 toivotuo 所说的那样被使用,它并没有像 Simon Zimmermann 所说的那样被淘汰(恕我直言)。

在我看来,另一种看法(由 libmagic 的原作者)。

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

于 2012-09-06T10:22:50.630 回答
10

在 python 2.6 中:

import shlex
import subprocess
mime = subprocess.Popen("/usr/bin/file --mime " + shlex.quote(PATH), shell=True, \
    stdout=subprocess.PIPE).communicate()[0]
于 2009-11-02T15:48:09.143 回答
7

您没有说明您使用的是什么 Web 服务器,但 Apache 有一个名为Mime Magic的漂亮小模块,当被告知这样做时,它使用它来确定文件的类型。它读取文件的一些内容并尝试根据找到的字符来确定它是什么类型。正如Dave Webb 提到的那样,python 下的MimeTypes 模块将起作用,只要扩展很方便。

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

于 2008-09-04T12:22:55.720 回答
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))

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

对于解压缩的 txt 文件(iostat 数据):text/plain;charset=us-ascii

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

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

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

于 2015-02-03T19:09:32.323 回答
7

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

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

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

可选的 strict 参数是一个标志,指定已知 MIME 类型的列表是否仅限于在 IANA 注册的官方类型。当 strict 为 True(默认)时,仅支持 IANA 类型;当 strict 为 False 时,还会识别一些额外的非标准但常用的 MIME 类型。

import mimetypes
print(mimetypes.guess_type("sample.html"))
于 2019-09-15T05:05:07.720 回答
6

在 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)
于 2016-09-06T19:55:29.897 回答
3

我首先尝试 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
于 2019-05-22T01:18:59.103 回答
1

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

于 2012-06-19T12:51:55.647 回答
1

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

Pygments 实际上是一个 Python 语法高亮库,但它有一种方法可以有根据地猜测您的文档是 500 种支持的文档类型中的哪一种。即c++ vs C# vs Python vs等

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 种文档格式中的哪一种,这非常有用。

于 2020-07-01T08:54:48.490 回答
0

我已经尝试了很多示例,但使用 Django mutagen可以很好地发挥作用。

检查文件是否为的示例mp3

from mutagen.mp3 import MP3, HeaderNotFoundError  

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

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

于 2017-08-19T10:33:56.660 回答
0

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

于 2018-07-25T04:43:28.890 回答