题
假设您想要将一堆文件保存在某个地方,例如保存在 BLOB 中。假设您想通过网页分发这些文件,并让客户端自动打开正确的应用程序/查看器。
假设:浏览器通过 HTTP 响应中的 mime-type(内容类型?)标头确定要使用哪个应用程序/查看器。
基于该假设,除了文件的字节之外,您还希望保存 MIME 类型。
如何找到文件的 MIME 类型?我目前使用的是 Mac,但这也应该适用于 Windows。
将文件发布到网页时浏览器是否会添加此信息?
有没有一个简洁的 python 库来查找这些信息?Web 服务还是(更好)可下载的数据库?
解决方案
toivotuo 建议的 python-magic 方法已经过时了。 Python 魔法 当前主干位于 Github,根据那里的自述文件,找到 MIME 类型,就是这样完成的。
# For MIME types
>>> import magic
>>> mime = magic.Magic(mime=True)
>>> mime.from_file("testdata/test.pdf")
'application/pdf'
>>>
其他提示
比使用 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 匹配。
这似乎很容易
>>> 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)
请参考 旧帖子
有 3 个不同的库包装了 libmagic。
其中 2 个可在 pypi 上使用(因此 pip install 可以工作):
- 文件魔法
- python 魔法
另一种与 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 有一个很好的小模块,名为 哑剧魔术 当被告知这样做时,它用它来确定文件的类型。它读取文件的一些内容,并尝试根据找到的字符确定文件的类型。并作为 戴夫·韦伯提到 这 MimeTypes 模块 在 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 数据):文本/纯文本;字符集=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'
Python 与 libmagic 的绑定
关于这个主题的所有不同答案都非常令人困惑,因此我希望通过对 libmagic 不同绑定的概述给出更清晰的信息。此前,mammadori 给出了 简短的回答 列出可用选项。
libmagic
- 模块名称:
magic
- pypi: 文件魔法
- 来源: https://github.com/file/file/tree/master/python
当确定文件 mime 类型时,只需调用所选择的工具 file
它的后端称为 libmagic
. 。(参见 项目主页.)该项目是在私有cvs存储库中开发的,但是有一个 github上的只读git镜像.
现在,如果您想将任何 libmagic 绑定与 python 一起使用,您将需要这个工具,它已经附带了自己的 python 绑定,称为 file-magic
. 。没有太多专门的文档,但您可以随时查看 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
对象使用 magic.open(flags)
如图所示 示例文件.
两个都 托伊沃托 和 ewr2san 使用这些 file-magic
绑定包含在 file
工具。他们错误地认为,他们正在使用 python-magic
包裹。 这似乎表明,如果两者 file
和 python-magic
已安装,python 模块 magic
指的是前一种。
python 魔法
- 模块名称:
magic
- pypi: python 魔法
- 来源: https://github.com/ahupp/python-magic
这就是西蒙·齐默尔曼 (Simon Zimmermann) 所说的图书馆 他的回答 并且也受雇于 克劳德·库隆贝 也 温文尔雅的外国佬.
文件魔法
- 模块名称:
magic
- pypi: 文件魔法
- 来源: https://github.com/aliles/filemagic
笔记: :该项目最后一次更新是在 2013 年!
由于基于相同的 c-api,该库与 file-magic
包括在 libmagic
. 。它仅被提及 马马多里 并且没有其他答案使用它。
mimetypes 模块仅根据文件扩展名识别文件类型。如果您尝试恢复不带扩展名的文件的文件类型,则 mimetypes 将不起作用。
我已经尝试了很多例子,但是使用 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)
对于字节数组类型数据,您可以使用魔法。from_buffer(_byte_array,mime = true)
我首先尝试 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
您可以使用 伊姆赫德 Python 模块。