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

时间:2008-09-04 12:07:27

标签: python mime

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

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

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

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

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

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

20 个答案:

答案 0 :(得分:185)

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

答案 1 :(得分:80)

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

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

答案 2 :(得分:43)

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

答案 3 :(得分:25)

这似乎很容易

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

答案 4 :(得分:10)

有3个不同的图书馆包含了libmagic。

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

  • filemagic
  • 蟒幻

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

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

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

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

答案 5 :(得分:9)

在python 2.6中:

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

答案 6 :(得分:6)

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

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

答案 7 :(得分:6)

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),其中 typeNone,如果类型不能被猜测(缺少或未知后缀)或形式为 { {1}},可用于 MIME content-type 标头。

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

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

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

答案 8 :(得分:6)

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

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

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

答案 9 :(得分:5)

在Python 3.x和webapp中,文件的url没有扩展名或虚假扩展名。你应该使用

安装python-magic
package com.wavedevelopers.databaseasynctaskdemo;

import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import android.widget.ListView;
import android.widget.Toast;

/**
 * Created by Haider885 on 25/08/2016.
 */
public class BackgrounTask extends AsyncTask<String,Product,String> {

    Context ctx;

    ProductAdapter productAdapter;

    Activity activity;
    ListView listView;

    BackgrounTask(Context ctx)
    {
        this.ctx = ctx;
        activity = (Activity) ctx;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected String doInBackground(String... params) {
        String method = params[0];
        DbOperation dbOperation = new DbOperation(ctx);
        if (method.equals("add_info"))
        {
            String id = params[1];
            String name = params[2];
            float price = Float.parseFloat(params[3]);
            float qty = Float.parseFloat(params[4]);
            float total = Float.parseFloat(params[5]);
            SQLiteDatabase db = dbOperation.getWritableDatabase();
            dbOperation.addProduct(db,id,name,price,qty,total);

            return "Saved...";


        }

        else if (method.equals("get_info"))
        {
            SQLiteDatabase db = dbOperation.getReadableDatabase();
            Cursor cursor = dbOperation.getInformation(db);

            productAdapter = new ProductAdapter(ctx,R.layout.display_product_row);

            listView = (ListView) activity.findViewById(R.id.display_listview);

            String id,name;
            float price,qty,total;

            while (cursor.moveToNext())
            {
                id = cursor.getString(cursor.getColumnIndex(ProductContract.ProductEntry.ID));
                name = cursor.getString(cursor.getColumnIndex(ProductContract.ProductEntry.NAME));
                price = cursor.getFloat(cursor.getColumnIndex(ProductContract.ProductEntry.PRICE));
                qty = cursor.getFloat(cursor.getColumnIndex(ProductContract.ProductEntry.QTY));
                total = cursor.getFloat(cursor.getColumnIndex(ProductContract.ProductEntry.TOTAL));

                Product product = new Product(id,name,price,qty,total);
                publishProgress(product);
            }

            return "get_info";


        }

        return null;
    }

    @Override
    protected void onProgressUpdate(Product... values) {
        productAdapter.add(values[0]);



    }

    @Override
    protected void onPostExecute(String result) {
        if (result.equals("get_info"))
        {
            listView.setAdapter(productAdapter);
        }
        else {
            Toast.makeText(ctx, result, Toast.LENGTH_SHORT).show();
        }
    }
}

对于Mac OS X,您还应该使用

安装libmagic
pip3 install python-magic

代码段

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)

答案 10 :(得分:5)

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'

答案 11 :(得分:5)

Python绑定到libmagic

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

libmagic

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

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

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

python-magic

这是Simon Zimmermann在his answer中谈论的库,Claude COULOMBEGringo Suave也使用了该库。

filemagic

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

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

答案 12 :(得分:4)

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

  

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

     

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

     

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

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

答案 13 :(得分:3)

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

答案 14 :(得分:1)

令我惊讶的是,没有人提到它,但是Pygments能够对特定的哑剧类型(尤其是文本文档)做出有根据的猜测。

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

答案 15 :(得分:0)

我尝试过很多例子,但Django mutagen很好玩。

检查文件是否为mp3

的示例
from mutagen.mp3 import MP3, HeaderNotFoundError  

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

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

答案 16 :(得分:0)

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

答案 17 :(得分:0)

For byte Array type data you can use magic.from_buffer(_byte_array,mime=True)

答案 18 :(得分:0)

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

答案 19 :(得分:-1)

您可以使用 imghdr Python模块。