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

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

How to find the mime type of a file in python?

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

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

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

您如何找到文件的MIME类型? 我目前在Mac上,但这也适用于Windows。

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

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


toivotuo建议的python-magic方法已经过时了。 Python-magic的当前主干位于Github,基于自述文件,找到MIME类型,就像这样。

1
2
3
4
5
6
# For MIME types
>>> import magic
>>> mime = magic.Magic(mime=True)
>>> mime.from_file("testdata/test.pdf")
'application/pdf'
>>>

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

如果用户正在上传文件,则HTTP帖子将包含文件的MIME类型以及数据。例如,Django使这些数据可用作UploadedFile对象的属性。


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

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

这相当于使用file(1)。

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


这似乎很容易

1
2
3
4
5
6
7
>>> 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


有3个不同的库包含libmagic。

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

  • filemagic
  • Python魔法

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

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

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

太糟糕了,不能直接在pypi上获得。


在python 2.6中:

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


Python绑定到libmagic

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

libmagic

  • 模块名称:magic
  • pypi:文件魔法
  • 来源:https://github.com/file/file/tree/master/python

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

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

1
2
3
4
5
6
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对象来使用库,如示例文件中所示。

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

Python魔法

  • 模块名称:magic
  • pypi:python-magic
  • 来源:https://github.com/ahupp/python-magic

这是Simon Zimmermann在他的回答中谈到的图书馆,也是Claude COULOMBE以及Gringo Suave所使用的图书馆。

filemagic

  • 模块名称:magic
  • pypi:filemagic
  • 来源:https://github.com/aliles/filemagic

注意:此项目最后更新于2013年!

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


你没有说明你正在使用什么样的Web服务器,但Apache有一个很好的小模块叫做Mime Magic,它用来确定文件的类型。它会读取文件的一些内容,并根据找到的字符尝试找出它的类型。而正如Dave Webb提到的python下的MimeTypes模块将起作用,只要扩展是很方便的。

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


@toivotuo的方法在python3下对我来说效果最好,最可靠。我的目标是识别没有可靠的.gz扩展名的gzip压缩文件。我安装了python3-magic。

1
2
3
4
5
6
7
8
9
10
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-焦油;字符集=二进制

对于bz2文件:
应用程序/ x-的bzip2;字符集=二进制

最后但并非最不重要的是一个.zip文件:
应用程序/压缩;字符集=二进制


2017年更新

不需要去github,它是以不同的名字在PyPi上:

1
2
3
pip3 install --user python-magic
# or:
sudo apt install python3-magic  # Ubuntu distro package

代码也可以简化:

1
2
3
4
>>> import magic

>>> magic.from_file('/tmp/img_3304.webp', mime=True)
'image/jpeg'

在Python 3.x和webapp中,文件的url没有扩展名或伪扩展名。你应该使用安装python-magic

1
pip3 install python-magic

对于Mac OS X,您还应该安装libmagic

1
brew install libmagic

代码段

1
2
3
4
5
6
7
8
9
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)

或者你可以在阅读中加入一个大小

1
2
3
4
5
6
7
8
9
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)


mimetypes模块只根据文件扩展名识别文件类型。如果您尝试恢复没有扩展名的文件的文件类型,mimetypes将无法正常工作。


我已经尝试了很多例子,但是Django mutagen很好用。

检查文件是否为mp3的示例

1
2
3
4
5
6
from mutagen.mp3 import MP3, HeaderNotFoundError  

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

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


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

mimetypes.guess_type(url, strict=True) Guess the type of a file based
on its filename or URL, given by url. The return value is a tuple
(type, encoding) where type is None if the type can’t be guessed
(missing or unknown suffix) or a string of the form 'type/subtype',
usable for a MIME content-type header.

encoding is None for no encoding or the name of the program used to
encode (e.g. compress or gzip). The encoding is suitable for use as a
Content-Encoding header, not as a Content-Transfer-Encoding header.
The mappings are table driven. Encoding suffixes are case sensitive;
type suffixes are first tried case sensitively, then case
insensitively.

The optional strict argument is a flag specifying whether the list of
known MIME types is limited to only the official types registered with
IANA. When strict is True (the default), only the IANA types are
supported; when strict is False, some additional non-standard but
commonly used MIME types are also recognized.

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

这可能已经过时了,但为什么不直接从Django使用UploadedFile.content_type?是不一样的?(https://docs.djangoproject.com/en/1.11/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.content_type)


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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
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

你可以使用imghdr Python模块。


推荐阅读

    linux改文件权限命令?

    linux改文件权限命令?,系统,工具,档案,权限,文件,信息,命令,目录,选项,用户,

    linux命令交换文件名?

    linux命令交换文件名?,命令,文件,数据,名称,工具,地址,软件,系统,基础知识,

    查看linux库类型命令?

    查看linux库类型命令?,系统,工作,信息,状态,电脑,命令,工具,代码,地址,发行,

    linux命令输出加时间?

    linux命令输出加时间?,时间,系统,名称,设备,命令,信息,管理,标准,数字,百度,l

    linux下替换文件命令?

    linux下替换文件命令?,文件,一致,评论,名称,标的,资料,工作,命令,字符串,内

    linux命令日志输出?

    linux命令日志输出?,系统,状态,命令,情况,对比,标准,实时,服务,下来,数据,怎

    linux寻找文件夹命令?

    linux寻找文件夹命令?,名称,命令,文件,位置,工作,标准,目录,子目录,文件名,

    linux把文件复制命令?

    linux把文件复制命令?,名字,文件,软件,系统,位置,目录,命令,源文件,目标,文

    linux浏览网页的命令?

    linux浏览网页的命令?,工作,系统,传播,地址,命令,环境,发行,信息,网络,基础,l

    linux文件夹合并命令?

    linux文件夹合并命令?,文件,对比,第一,下来,命令,文件夹,两个,字段,内容,数

    linux下文件创建命令?

    linux下文件创建命令?,名字,名称,首次,命令,文件,系统,密码,文件名,文件夹,

    linux命令行安装文件?

    linux命令行安装文件?,软件,官网,密码,中心,电脑,文件,命令,终端,指令,版本,L

    linux解压文件命令行?

    linux解压文件命令行?,系统,电脑,命令,文件,平台,名称,软件,管理,标准,目录,

    linux网卡类型命令?

    linux网卡类型命令?,网络,系统,地址,信息,设备,状态,服务,名称,名字,网卡,如

    linux命令访问网页?

    linux命令访问网页?,地址,传播,网络,系统,软件,网址,密码,服务,数据,首次,lin

    linux命令编辑文件?

    linux命令编辑文件?,系统,状态,电脑,命令,数据,标准,不了,名称,发行,网络,Lin

    linux命令输出计算?

    linux命令输出计算?,标准,地址,工作,信息,系统,命令,软件,数据,文件,控制台,l

    linux文件乱码命令?

    linux文件乱码命令?,系统,环境,乱码,信息,状态,盘中,文件,字符集,中文,文件

    linux持续命令输出?

    linux持续命令输出?,系统,工作,地址,信息,情况,状态,数据,管理,工具,指标,lin