Как найти MIME-тип файла в Python?

Допустим, вы хотите где-то сохранить кучу файлов, например, в больших двоичных объектах. Допустим, вы хотите отправить эти файлы через веб-страницу, и клиент автоматически откроет правильное приложение / средство просмотра.

Предположение: браузер определяет, какое приложение / средство просмотра использовать с помощью заголовка mime-type (content-type?) В HTTP-ответе.

Исходя из этого предположения, помимо байтов файла, вы также хотите сохранить тип MIME.

Как найти MIME-тип файла? В настоящее время я использую Mac, но это также должно работать в Windows.

Добавляет ли браузер эту информацию при публикации файла на веб-странице?

Есть ли аккуратная библиотека Python для поиска этой информации? WebService или (что еще лучше) загружаемая база данных?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
210
0
191 611
20
Перейти к ответу Данный вопрос помечен как решенный

Ответы 20

модуль mimetypes в стандартной библиотеке будет определять / угадывать тип MIME по расширению файла.

Если пользователи загружают файлы, сообщение HTTP будет содержать MIME-тип файла вместе с данными. Например, Django делает эти данные доступными как атрибут объекта UploadedFile.

Если файлы хранятся в больших двоичных объектах, как указано в вопросе, вы можете не знать расширение файла.

Mechanical snail 01.08.2011 10:05

Также не забывайте дезинфицировать файлы при их выводе другим пользователям: stackoverflow.com/questions/1745743/…

Jonatan Littke 30.11.2011 13:20

Расширения файлов не являются надежным способом определения типа MIME.

Cerin 29.12.2013 00:49

Повторяя некоторые из приведенных выше комментариев, лучшее решение - в Ответ Саймона.

tripleee 12.11.2014 16:49

import mimetypesmimetypes.MimeTypes().guess_type(filename)[0]

Jonathan 06.03.2015 23:36

в python 3.6 это работает: mimetypes.guess_type(path_file_to_upload)[1]

JinSnow 16.03.2017 23:03

Хотя @cerin прав в том, что расширения файлов ненадежны, я только что обнаружил, что точность python-magic (как предлагается в верхнем ответе) еще ниже, что подтверждается github.com/s3tools/s3cmd/issues/198. Так что mimetypes кажется мне лучшим кандидатом.

danqing 07.08.2017 04:50

Хотя @Cerin в основном прав, получение text/plain для CSS, JavaScript и т.д. и text/xml (как ASCII) для XML, содержащего много не-ASCII символов, совершенно бесполезно и даже потенциально опасно. Следовательно, на данный момент миметипы - это лучший способ.

dariok 03.11.2019 20:06

@JinSnow Спасибо за подсказку по синтаксису. Я бы по умолчанию проверял часть [0] - тип, а не кодировку. Ответ для меня обычно выглядел как ("application/json", None).

Noumenon 04.12.2019 17:59

Начиная с Python 3.8 mimetypes.guess_type теперь принимает объект, подобный Path. Таким образом, он совместим с модулем pathlib Python. выпуск: bugs.python.org/issue34926

inostia 22.01.2021 10:39

Вы не указали, какой веб-сервер вы использовали, но у Apache есть небольшой симпатичный модуль под названием Mime Magic, который он использует для определения типа файла, когда ему об этом говорят. Он считывает часть содержимого файла и пытается определить его тип на основе найденных символов. И как Упомянутый Дэйв Уэбб, Модуль MimeTypes под python будет работать, при условии, что расширение удобно.

В качестве альтернативы, если вы сидите в системе UNIX, вы можете использовать sys.popen('file -i ' + fileName, mode='r') для получения типа MIME. В Windows должна быть эквивалентная команда, но я не уверен, что это такое.

Теперь вы можете просто выполнить subprocess.check_output (['file', '-b', '--mime', filename])

Nathan Villaescusa 06.05.2011 09:34

На самом деле нет причин прибегать к использованию внешнего инструмента, когда python-magic делает то же самое, и все это удобно и уютно.

damd 11.03.2013 16:38

в 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), как в ответе Саймона.

Mechanical snail 01.08.2011 10:03

Это зависит от операционной системы. Например, в Mac OS X у вас есть «файл», но нет libmagic в нормальной среде.

rptb1 21.05.2013 12:15

мне это кажется небезопасным, PATH следует избегать. idk, что такое эквивалент Python, но разработчики php будут использовать Popen("/usr/bin/file --mime ".escapeshellarg(PATH)); - например, ваш код не работает в файлах, содержащих символы новой строки или кавычки, возможно, также $ dollarign, но это также защитит вас от хакеров, выполняющих PATH='; rm -rfv / и такую ​​инъекцию оболочки

hanshenrik 09.02.2021 03:40

Более надежным способом, чем использование библиотеки 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

Daren Thomas 04.05.2010 13:22

@DarenThomas: Как упоминалось в ответе mammadori, этот ответ нет устарел и отличается от решения Саймона Циммермана. Если у вас установлена ​​файловая утилита, вы, вероятно, сможете использовать это решение. У меня работает с file-5.32. В gentoo у вас также должен быть включен USE-флаг python для пакета файлов.

bodo 22.06.2018 11:58
Ответ принят как подходящий

Метод python-magic, предложенный Toivotuo, устарел. Python-магия текущий транк находится в Github и на основе читаемого файла там поиск MIME-типа выполняется следующим образом.

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

Спасибо за комментарий! обратите внимание, что «выше» - сложная концепция в stackoverflow, поскольку порядок группируется по голосам и упорядочивается случайным образом внутри групп. Я предполагаю, что вы ссылаетесь на ответ @toivotuo.

Daren Thomas 04.05.2010 13:20

Да, на момент написания этого ответа у меня не было достаточно «очков» для создания комментариев. Но мне, наверное, следовало написать это как комментарий, чтобы @toivotuo мог отредактировать свой вопрос.

Simon Zimmermann 27.06.2010 10:59

rpm -qf /usr/lib/python2.7/site-packages/magic.py -i URL: darwinsys.com/file Резюме: привязки Python для libmagic API rpm -qf / usr / bin / file -i Имя: URL-адрес файла: darwinsys.com/file python -magic от darwinsys.com/file, который поставляется с Linux Fedora, работает так, как сказал @toivotuo. И кажется более мейнстримом.

Sérgio 22.10.2011 15:52

Поскольку волшебная библиотека не является стандартной библиотекой python, это очень неуклюже :-( Есть ли способ напрямую использовать команду unix file? К сожалению, s = os.system("file -b --mime-type /home/me/myfile.bz2") не записывает MIME в s, а только выводит его на стандартный вывод: - (

sumid 17.05.2012 21:57

Помните, что пакет debian / ubuntu под названием python-magic отличается от пакета pip с тем же именем. Оба являются import magic, но имеют несовместимое содержимое. Подробнее см. stackoverflow.com/a/16203777/3189.

Hamish Downer 28.04.2015 14:14

Модуль magic поступает от filemagic на pypi

ThorSummoner 18.07.2015 20:05

Проверьте мой ответ в контексте отсутствия расширения файла или ложного расширения файла, Python 3.X и веб-приложения stackoverflow.com/a/39356849/1209842

Claude COULOMBE 06.09.2016 23:11

Как я прокомментировал ответ toivotuo, он не устарел! Вы говорите о другой библиотеке. Не могли бы вы удалить или заменить это утверждение в своем ответе? В настоящее время это действительно затрудняет поиск лучшего решения.

bodo 22.06.2018 12:04

js и css с этим просто "текст / простой"!

Manoj Acharya 05.05.2019 20:32

Как сказал @ManojAcharya, это не даст полезных результатов при применении к большинству файлов, связанных с Интернетом. В основном все будет в формате text / plain, за исключением файла XML, который будет либо text / html, либо text / xml (!), В зависимости от настроения библиотеки. Когда вам нужно получить результаты для веб-файлов, вы должны использовать модуль mimetypes (см. Ответы dave-webb, oetzi и других ниже).

dariok 03.11.2019 19:58

Он не работал с последней версией Python

Dhiraj 15.12.2020 08:50

вы можете использовать модуль imghdr Python.

Это бесполезный комментарий, потому что он не дает примеров и не говорит, как и почему imghdr может здесь помочь.

erikbwork 17.12.2013 20:11

Да, я это понимаю. Это было больше года назад, но, возможно, вы все еще можете обновить его, потому что все еще есть люди, которые ищут этот вопрос, как и я. Если вам понадобится помощь, вы можете мне сказать.

erikbwork 18.12.2013 14:33

Это работает только для очень ограниченного списка типов изображений. Он не имеет представления о текстовых файлах, сжатых архивах, форматах документов и т. д.

tripleee 12.11.2014 16:52

Модуль mimetypes просто распознает тип файла на основе расширения файла. Если вы попытаетесь восстановить тип файла без расширения, mimetypes не будут работать.

Не думаю, что это правда. Тип MIME предназначен для того, чтобы сообщить другим о формате данных, а не о том, как узнать формат данных самостоятельно. Если вы используете инструмент, который определяет формат только на основе расширения и распечатывает типы MIME, вы не можете использовать этот инструмент, если нет расширений файлов. Но возможны и другие способы угадать формат, например, проверяя с помощью парсера.

erikbwork 17.12.2013 20:13

Есть 3 разные библиотеки, в которые входит libmagic.

2 из них доступны на pypi (поэтому установка pip будет работать):

  • filemagic
  • питон-магия

И еще один, похожий на python-magic, доступен непосредственно в последних исходных кодах libmagic, и он, вероятно, есть в вашем дистрибутиве Linux.

В Debian пакет python-magic посвящен этому, и он используется, как сказал toivotuo, и не устарел, как сказал Саймон Циммерманн (IMHO).

Мне кажется, что это еще один вариант (от автора libmagic).

Жаль, что он недоступен непосредственно на pypi.

Я для удобства добавил репо: github.com/mammadori/magic-python так можно: pip install -e git://github.com/mammadori/magic-python.git#egg=Magic_file_e‌​xtensions

mammadori 06.09.2012 19:02

Кажется, это очень просто

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

Я не думаю, что urllib требуется в вашем примере.

BrotherJack 08.08.2014 18:38

для Python 3.X замените import urllib на запрос на импорт из urllib. А затем используйте "запрос" вместо urllib.

Arjun Thakur 01.06.2016 12:42

Также работает для python 2.7

Jay Modi 04.01.2018 15:46

решение @oetzi использует этот модуль, но он более простой.

Garrett 05.12.2019 09:56

Метод @toivotuo работал лучше всего и наиболее надежно для меня под python3. Моя цель состояла в том, чтобы идентифицировать сжатые файлы, которые не имеют надежного расширения .gz. Я установил 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; charset = двоичный

для распакованного txt файла (данные iostat): текст / простой; кодировка = us-ascii

для файла tar: приложение / x-tar; charset = двоичный

для файла bz2: приложение / x-bzip2; charset = двоичный

и последний, но не менее важный для меня файл .zip: приложение / zip; charset = двоичный

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

Будет ли загружен весь файл?

吴毅凡 17.03.2017 14:29

Нет, это поток, поэтому обычно всего несколько байтов.

Claude COULOMBE 17.03.2017 18:19

Я редактировал response.readline () или response.read (128) Спасибо!

Claude COULOMBE 25.03.2017 07:10

Я пробовал много примеров, но с Django мутаген работает хорошо.

Пример проверки того, являются ли файлы mp3

from mutagen.mp3 import MP3, HeaderNotFoundError  

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

Обратной стороной является то, что ваша способность проверять типы файлов ограничена, но это отличный способ, если вы хотите не только проверить тип файла, но и получить доступ к дополнительной информации.

мне также нужно проверить безопасность

Artem Bernatskyi 19.08.2017 14:49

Обновление 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?

kumbhani bhavesh 13.12.2018 12:52

Конечно, а почему бы и нет ??

Gringo Suave 14.12.2018 03:31

Возможно, он уже устарел, но почему бы не использовать UploadedFile.content_type непосредственно из Django? Разве не то же самое? (https://docs.djangoproject.com/en/1.11/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.content_type)

Привязки Python к libmagic

Все разные ответы на эту тему очень сбивают с толку, поэтому я надеюсь внести немного больше ясности в этот обзор различных привязок libmagic. Ранее mammadori предоставляла список доступных опций в краткий ответ.

libmagic

При определении mime-типа файлов инструмент выбора просто называется file, а его внутренняя часть называется libmagic. (См. Домашняя страница проекта.) Проект разработан в частном cvs-репозитории, но есть зеркало git только для чтения на github.

Теперь этот инструмент, который вам понадобится, если вы хотите использовать какие-либо привязки libmagic с python, уже поставляется со своими собственными привязками python, называемыми file-magic. Для них не так много специальной документации, но вы всегда можете взглянуть на страницу руководства c-библиотеки: man libmagic. Основное использование описано в файл readme:

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. Похоже, это указывает на то, что если установлены как file, так и python-magic, модуль Python magic относится к первому.

питон-магия

Это библиотека, о которой Саймон Циммерманн говорит в его ответ и которая также используется Клод КУЛОМБ, а также Гринго Вежливый.

filemagic

Примечание: Этот проект последний раз обновлялся в 2013 году!

Поскольку эта библиотека основана на том же c-api, она имеет некоторое сходство с file-magic, включенным в libmagic. Он упоминается только маммадори, и никакой другой ответ не использует его.

Для данных типа байтового массива вы можете использовать magic.from_buffer (_byte_array, mime = True)

Сначала я пробую библиотеку 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

Python 3 ссылка: 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.

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

Я удивлен, что об этом никто не упомянул, но Пигменты может сделать обоснованное предположение о MIME-типе, в частности, текстовых документов.

Pygments на самом деле является библиотекой подсветки синтаксиса Python, но у нее есть метод, который позволит сделать обоснованное предположение о том, какой из 500 поддерживаемых типов документов является вашим документом. то есть С ++ против C# против Python против и т. д.

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 форматов документов используется, это чертовски полезно.

13 лет спустя ...
Большинство ответов для python 3 на этой странице либо устарели, либо неполны. Чтобы получить mime-тип файла на python3, я обычно использую:

import mimetypes
mt = mimetypes.guess_type("file.ext")[0]

От Документы Python:

mimetypes.guess_type(url, strict = True)

Угадайте тип файла на основе его имени файла, пути или URL-адреса, заданного url. URL-адрес может быть строкой или объект в виде пути.

Возвращаемое значение - это кортеж (type, encoding), где тип - это None, если тип невозможно угадать (отсутствующий или неизвестный суффикс), или строка формы 'type/subtype', которую можно использовать для заголовка MIME Тип содержимого.

кодирование - это None для отсутствия кодирования или имени программы, используемой для кодирования (например, компресс или gzip). Кодировка подходит для использования в качестве заголовка Content-Encoding, нет в качестве заголовка Content-Transfer-Encoding. Отображения управляются таблицами. Суффиксы кодирования чувствительны к регистру; суффиксы типов сначала проверяются с учетом регистра, а затем без учета регистра.

Необязательный аргумент строгий - это флаг, определяющий, ограничен ли список известных типов MIME только официальными типами зарегистрирован в IANA. Когда строгий - True (по умолчанию), поддерживаются только типы IANA; когда строгий - False, также распознаются некоторые дополнительные нестандартные, но часто используемые типы MIME.

Изменено в версии 3.8: Добавлена ​​поддержка URL-адреса, являющегося объект в виде пути.

Другие вопросы по теме