Допустим, вы хотите где-то сохранить кучу файлов, например, в больших двоичных объектах. Допустим, вы хотите отправить эти файлы через веб-страницу, и клиент автоматически откроет правильное приложение / средство просмотра.
Предположение: браузер определяет, какое приложение / средство просмотра использовать с помощью заголовка mime-type (content-type?) В HTTP-ответе.
Исходя из этого предположения, помимо байтов файла, вы также хотите сохранить тип MIME.
Как найти MIME-тип файла? В настоящее время я использую Mac, но это также должно работать в Windows.
Добавляет ли браузер эту информацию при публикации файла на веб-странице?
Есть ли аккуратная библиотека Python для поиска этой информации? WebService или (что еще лучше) загружаемая база данных?






модуль mimetypes в стандартной библиотеке будет определять / угадывать тип MIME по расширению файла.
Если пользователи загружают файлы, сообщение HTTP будет содержать MIME-тип файла вместе с данными. Например, Django делает эти данные доступными как атрибут объекта UploadedFile.
Также не забывайте дезинфицировать файлы при их выводе другим пользователям: stackoverflow.com/questions/1745743/…
Расширения файлов не являются надежным способом определения типа MIME.
Повторяя некоторые из приведенных выше комментариев, лучшее решение - в Ответ Саймона.
import mimetypesmimetypes.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 кажется мне лучшим кандидатом.
Хотя @Cerin в основном прав, получение text/plain для CSS, JavaScript и т.д. и text/xml (как ASCII) для XML, содержащего много не-ASCII символов, совершенно бесполезно и даже потенциально опасно. Следовательно, на данный момент миметипы - это лучший способ.
@JinSnow Спасибо за подсказку по синтаксису. Я бы по умолчанию проверял часть [0] - тип, а не кодировку. Ответ для меня обычно выглядел как ("application/json", None).
Начиная с Python 3.8 mimetypes.guess_type теперь принимает объект, подобный Path. Таким образом, он совместим с модулем pathlib Python. выпуск: bugs.python.org/issue34926
Вы не указали, какой веб-сервер вы использовали, но у Apache есть небольшой симпатичный модуль под названием Mime Magic, который он использует для определения типа файла, когда ему об этом говорят. Он считывает часть содержимого файла и пытается определить его тип на основе найденных символов. И как Упомянутый Дэйв Уэбб, Модуль MimeTypes под python будет работать, при условии, что расширение удобно.
В качестве альтернативы, если вы сидите в системе UNIX, вы можете использовать sys.popen('file -i ' + fileName, mode='r') для получения типа MIME. В Windows должна быть эквивалентная команда, но я не уверен, что это такое.
Теперь вы можете просто выполнить subprocess.check_output (['file', '-b', '--mime', filename])
На самом деле нет причин прибегать к использованию внешнего инструмента, когда python-magic делает то же самое, и все это удобно и уютно.
в 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 следует избегать. idk, что такое эквивалент Python, но разработчики php будут использовать Popen("/usr/bin/file --mime ".escapeshellarg(PATH)); - например, ваш код не работает в файлах, содержащих символы новой строки или кавычки, возможно, также $ dollarign, но это также защитит вас от хакеров, выполняющих PATH='; rm -rfv / и такую инъекцию оболочки
Более надежным способом, чем использование библиотеки 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
@DarenThomas: Как упоминалось в ответе mammadori, этот ответ нет устарел и отличается от решения Саймона Циммермана. Если у вас установлена файловая утилита, вы, вероятно, сможете использовать это решение. У меня работает с file-5.32. В gentoo у вас также должен быть включен USE-флаг python для пакета файлов.
Метод 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.
Да, на момент написания этого ответа у меня не было достаточно «очков» для создания комментариев. Но мне, наверное, следовало написать это как комментарий, чтобы @toivotuo мог отредактировать свой вопрос.
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. И кажется более мейнстримом.
Поскольку волшебная библиотека не является стандартной библиотекой python, это очень неуклюже :-( Есть ли способ напрямую использовать команду unix file? К сожалению, s = os.system("file -b --mime-type /home/me/myfile.bz2") не записывает MIME в s, а только выводит его на стандартный вывод: - (
Помните, что пакет debian / ubuntu под названием python-magic отличается от пакета pip с тем же именем. Оба являются import magic, но имеют несовместимое содержимое. Подробнее см. stackoverflow.com/a/16203777/3189.
Проверьте мой ответ в контексте отсутствия расширения файла или ложного расширения файла, Python 3.X и веб-приложения stackoverflow.com/a/39356849/1209842
Как я прокомментировал ответ toivotuo, он не устарел! Вы говорите о другой библиотеке. Не могли бы вы удалить или заменить это утверждение в своем ответе? В настоящее время это действительно затрудняет поиск лучшего решения.
js и css с этим просто "текст / простой"!
Как сказал @ManojAcharya, это не даст полезных результатов при применении к большинству файлов, связанных с Интернетом. В основном все будет в формате text / plain, за исключением файла XML, который будет либо text / html, либо text / xml (!), В зависимости от настроения библиотеки. Когда вам нужно получить результаты для веб-файлов, вы должны использовать модуль mimetypes (см. Ответы dave-webb, oetzi и других ниже).
Он не работал с последней версией Python
вы можете использовать модуль imghdr Python.
Это бесполезный комментарий, потому что он не дает примеров и не говорит, как и почему imghdr может здесь помочь.
Да, я это понимаю. Это было больше года назад, но, возможно, вы все еще можете обновить его, потому что все еще есть люди, которые ищут этот вопрос, как и я. Если вам понадобится помощь, вы можете мне сказать.
Это работает только для очень ограниченного списка типов изображений. Он не имеет представления о текстовых файлах, сжатых архивах, форматах документов и т. д.
Модуль mimetypes просто распознает тип файла на основе расширения файла. Если вы попытаетесь восстановить тип файла без расширения, mimetypes не будут работать.
Не думаю, что это правда. Тип MIME предназначен для того, чтобы сообщить другим о формате данных, а не о том, как узнать формат данных самостоятельно. Если вы используете инструмент, который определяет формат только на основе расширения и распечатывает типы MIME, вы не можете использовать этот инструмент, если нет расширений файлов. Но возможны и другие способы угадать формат, например, проверяя с помощью парсера.
Есть 3 разные библиотеки, в которые входит libmagic.
2 из них доступны на pypi (поэтому установка pip будет работать):
И еще один, похожий на 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_extensions
Кажется, это очень просто
>>> 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 требуется в вашем примере.
для Python 3.X замените import urllib на запрос на импорт из urllib. А затем используйте "запрос" вместо urllib.
Также работает для python 2.7
решение @oetzi использует этот модуль, но он более простой.
Метод @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)
Будет ли загружен весь файл?
Нет, это поток, поэтому обычно всего несколько байтов.
Я редактировал response.readline () или response.read (128) Спасибо!
Я пробовал много примеров, но с Django мутаген работает хорошо.
Пример проверки того, являются ли файлы mp3
from mutagen.mp3 import MP3, HeaderNotFoundError
try:
audio = MP3(file)
except HeaderNotFoundError:
raise ValidationError('This file should be mp3')
Обратной стороной является то, что ваша способность проверять типы файлов ограничена, но это отличный способ, если вы хотите не только проверить тип файла, но и получить доступ к дополнительной информации.
мне также нужно проверить безопасность
Обновление 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?
Конечно, а почему бы и нет ??
Возможно, он уже устарел, но почему бы не использовать UploadedFile.content_type непосредственно из Django? Разве не то же самое? (https://docs.djangoproject.com/en/1.11/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.content_type)
Все разные ответы на эту тему очень сбивают с толку, поэтому я надеюсь внести немного больше ясности в этот обзор различных привязок libmagic. Ранее mammadori предоставляла список доступных опций в краткий ответ.
magicПри определении 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 относится к первому.
magicЭто библиотека, о которой Саймон Циммерманн говорит в его ответ и которая также используется Клод КУЛОМБ, а также Гринго Вежливый.
magicПримечание: Этот проект последний раз обновлялся в 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-адреса, являющегося объект в виде пути.
Если файлы хранятся в больших двоичных объектах, как указано в вопросе, вы можете не знать расширение файла.