ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

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

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

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


S
Smart Manoj

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

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

感谢您的评论!请注意,“以上”在 stackoverflow 中是一个困难的概念,因为排序是按投票分组的,并且在组内随机排序。我猜你指的是@toivotuo 的回答。
是的,在撰写此回复时,我没有足够的“积分”来创建评论。但我可能应该把它写成评论,以便@toivotuo 可以编辑他的问题。
rpm -qf /usr/lib/python2.7/site-packages/magic.py -i URL:darwinsys.com/file 摘要:libmagic API 的 Python 绑定 rpm -qf /usr/bin/file -i 名称:文件 URL: darwinsys.com/file 来自 darwinsys.com/file 的 python-magic 和 Linux Fedora 的工作方式就像 @toivotuo 所说的那样。而且似乎更主流。
请注意,名为 python-magic 的 debian/ubuntu 包与同名的 pip 包不同。两者都是 import magic,但内容不兼容。有关更多信息,请参见stackoverflow.com/a/16203777/3189
正如我评论 toivotuo 的答案,它并没有过时!你在谈论一个不同的图书馆。您能否在答案中删除或替换该陈述?目前,它使找到最佳解决方案变得非常困难。
j
jfs

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

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


如果文件存储在 BLOB 中,如问题中所述,您可能不知道文件扩展名。
文件扩展名不是确定 mime 类型的可靠方法。
import mimetypes mimetypes.MimeTypes().guess_type(filename)[0]
在 python 3.6 这有效:mimetypes.guess_type(path_file_to_upload)[1]
虽然@cerin 认为文件扩展名不可靠是对的,但我刚刚发现 python-magic 的准确性(如最佳答案中所建议)甚至更低,正如 github.com/s3tools/s3cmd/issues/198 所证实的那样。所以,mimetypes 对我来说似乎是一个更好的候选人。
t
toivotuo

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


有关 python-magic 的更新使用,请参阅 Simon Zimmermann 的帖子
@DarenThomas:正如 mammadori 的回答中提到的,这个答案并没有过时,并且与 Simon Zimmermann 的解决方案不同。如果您安装了文件实用程序,您可能可以使用此解决方案。它适用于我的 file-5.32。在 gentoo 上,您还必须为文件包启用 python USE-flag。
S
Smart Manoj

这似乎很容易

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

请参考Old Post

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

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

我认为您的示例中不需要 urllib。
对于 Python 3.X,将 import urllib 替换为 from urllib import request。然后使用“请求”而不是 urllib
也适用于 python 2.7
@oetzi 的 solution 使用这个模块,但更简单。
P
Pedro Lobito

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

Live Demo

Python docs

mimetypes.guess_type(url, strict=True)

根据 url 给出的文件名、路径或 URL 猜测文件的类型。 URL 可以是字符串或 path-like object

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

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

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

在 3.8 版更改: 添加了对 url 作为 path-like object 的支持。


如果文件路径没有扩展名,则 mime 无法获得正确的结果。
b
bodo

Python 绑定到 libmagic

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

libmagic

模块名称:魔法

pypi:文件魔术

来源:https://github.com/file/file/tree/master/python

在确定文件 mime 类型时,选择的工具简称为 file,其后端称为 libmagic。 (请参阅 Project home page。)该项目是在私有 cvs-repository 中开发的,但有一个 read-only git mirror on github

现在,如果您想在 python 中使用任何 libmagic 绑定,您将需要这个工具,它已经附带了自己的名为 file-magic 的 python 绑定。没有太多专门的文档,但您可以随时查看 c-library 的手册页:man libmagicreadme file 中描述了基本用法:

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 对象来使用该库,如 example file 所示。

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

蟒蛇魔术

模块名称:魔法

pypi: 蟒蛇魔法

来源:https://github.com/ahupp/python-magic

这是 Simon Zimmermann 在 his answer 中谈到的库,它也被 Claude COULOMBEGringo Suave 使用。

文件魔术

模块名称:魔法

pypi:文件魔术

来源:https://github.com/aliles/filemagic

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

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


G
Gringo Suave

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 文件做同样的事情吗?
当然,为什么不呢??
m
mammadori

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

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

文件魔术

蟒蛇魔术

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

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

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

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


为方便起见,我添加了一个存储库:github.com/mammadori/magic-python 这样您就可以:pip install -e git://github.com/mammadori/magic-python.git#egg=Magic_file_extensions
a
apito

在 python 2.6 中:

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

这是不必要的,因为 file 命令基本上只是 libmagic 的包装。您也可以使用 python 绑定(python-magic),就像西蒙的回答一样。
这取决于操作系统。例如,在 Mac OS X 上,您有“文件”,但在正常环境中没有 libmagic。
这对我来说看起来不安全, PATH 应该被转义。知道 Python 的等价物是什么,但 php 开发人员会使用 Popen("/usr/bin/file --mime ".escapeshellarg(PATH)); - 例如,您的代码在包含换行符或引号的文件上可能会失败,可能还有 $dollarsign,但它也可以保护您免受黑客执行 PATH='; rm -rfv / 和此类 shell 注入
C
Community

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

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


现在你可以做 subprocess.check_output(['file', '-b', '--mime', filename])
当 python-magic 做同样的事情时,真的没有理由求助于使用外部工具,所有这些都是包装和舒适的。
e
ewr2san

@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;字符集=二进制


o
oetzi

蟒蛇 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"))

C
Claude COULOMBE

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

它会加载整个文件吗?
不,它是一个流,所以通常只有几个字节。
我已经通过 response.readline() 或 response.read(128) 进行了编辑,谢谢!
J
Jak Liao

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

E
Eric McLachlan

我很惊讶没有人提到它,但 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 种文档格式中的哪一种,这非常有用。


H
Helder

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


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

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


A
Artem Bernatskyi

我尝试了很多示例,但使用 Django mutagen 效果很好。

检查文件是否为 mp3 的示例

from mutagen.mp3 import MP3, HeaderNotFoundError  

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

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


我还需要检查安全性