Як знайти тип файлу mime у python?


194

Скажімо, ви хочете десь зберегти купу файлів, наприклад, у BLOB. Скажімо, ви хочете передати ці файли через веб-сторінку і дати клієнту автоматично відкрити правильну програму / переглядач.

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

Виходячи з цього припущення, крім байтів файлу, ви також хочете зберегти тип MIME.

Як би ви знайшли тип файлу MIME? Зараз я на Mac, але це має працювати і в Windows.

Чи додає браузер цю інформацію під час публікації файлу на веб-сторінці?

Чи є акуратна бібліотека пітонів для пошуку цієї інформації? Веб-сервіс або (ще краще) завантажувана база даних?

Відповіді:


218

Магічний метод пітона, запропонований toivotuo, застарів. Поточний стовбур Python-magic знаходиться в Github, і на основі readme там, пошук типу MIME, робиться так.

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

17
дякую за коментар! зауважте, що "вище" є складним поняттям у потоковому потоці, оскільки впорядкованість групується за голосами та впорядковується випадковим чином у межах груп. Я здогадуюсь, ви посилаєтесь на відповідь @ toivotuo.
Дарен Томас

1
Так, у мене не було достатньо "балів" для створення коментарів під час написання цієї відповіді. Але я, мабуть, повинен був написати це як коментар, щоб @toivotuo міг відредагувати своє запитання.
Саймон Цимерманн

1
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. І здається більш основним потоком.
Серхіо

7
Будьте уважні, що пакет debian / ubuntu під назвою python-magic відрізняється від однойменного пакету pip. Обидва є, import magicале мають несумісний вміст. Див. Stackoverflow.com/a/16203777/3189 для отримання додаткової інформації.
Гаміш Даунер

1
Як я коментував відповідь toivotuo, вона не застаріла! Ви говорите про іншу бібліотеку. Чи можете ви видалити або замінити це твердження у своїй відповіді? Наразі робить найкраще рішення справді важким.
bodo

87

Модуль mimetypes у стандартній бібліотеці визначатиме / відгадує тип MIME з розширення файлу.

Якщо користувачі завантажують файли, повідомлення HTTP міститиме файл MIME поряд із даними. Наприклад, Джанго робить ці дані доступними як атрибут об'єкта UploadFile .


12
Якщо файли зберігаються в BLOB, як зазначено в питанні, ви можете не знати розширення файлу.
Механічний равлик

55
Розширення файлів не є надійним способом визначення типу mime.
Серін

13
import mimetypes mimetypes.MimeTypes().guess_type(filename)[0]
Джонатан

4
у python 3.6 це працює:mimetypes.guess_type(path_file_to_upload)[1]
JinSnow

3
Хоча @cerin має рацію, що розширення файлів не є надійними, я щойно виявив, що точність python-magic(як це пропонується у верхній відповіді) буде ще нижчою, що підтверджено github.com/s3tools/s3cmd/isissue/198 . Отже, mimetypesздається мені кращим кандидатом.
danqing

46

Більш надійним способом, ніж використання бібліотеки міметипів, було б використання пакету python-magic.

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

Це було б рівноцінно використанню файлу (1).

На Django можна також переконатися, що тип MIME відповідає тому, що використовується в завантаженому файлі uploadFile.content_type.


2
Дивіться публікацію Саймона Цимермана про оновлене використання магії пітон
Дарен Томас

@DarenThomas: Як згадується у відповіді mammadori, ця відповідь не застаріла і не відрізняється від рішення Саймона Цимермана. Якщо у вас встановлена ​​утиліта файлів, ви, ймовірно, можете використовувати це рішення. Для мене працює файл-5.32. Для gentoo також потрібно включити прапор python USE для файлового пакету.
bodo

36

Це здається дуже простим

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

Оновлення - Відповідно до коментаря @Garrets, у python 3 це простіше:

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

4
Я не думаю, що у вашому прикладі потрібен urllib.
BrotherJack

5
для Python 3.X замініть імпортний urllib на запит на імпорт urllib. А потім використовуйте "запит" замість urllib
Арджун Тхакур

1
Також працює для python 2.7
Jay Modi

@ Оое ігрове рішення використовує цей модуль, але є більш простим.
Гаррет

11

Існують 3 різні бібліотеки, які обгортають лібмагічні.

2 з них доступні на pypi (так що встановлення pip буде працювати):

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

І інша, подібна до python-magic, доступна безпосередньо в останніх лібмагічних джерелах, і це, можливо, є у вашому дистрибутиві Linux.

У Debian пакет python-magic є про це, і він використовується як сказано toivotuo, і він не застарів, як сказав Саймон Ціммерманн (IMHO).

Мені здається, ще один прийом (автор оригіналу libmagic).

Дуже погано недоступно безпосередньо на піпі.


Я додав репо для зручності: github.com/mammadori/magic-python таким чином можна: pip install -e git://github.com/mammadori/magic-python.git#egg=Magic_file_extensions
mammadori

10

в python 2.6:

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

6
Це непотрібно, оскільки fileкоманда в основному є лише обгорткою навколо libmagic. Ви можете просто використовувати зв'язування пітона (python-magic), як у відповіді Саймона.
Механічний равлик

6
Це залежить від операційної системи. Наприклад, у Mac OS X у вас є "файл", але не лібмагічний у звичайному середовищі.
rptb1

9

Оновлення 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?
кумбханібхавеш

Звісно, ​​чому б ні??
Gringo Suave

9

Прив’язки пітона до лібмагічних

Усі різні відповіді на цю тему дуже заплутані, тому я сподіваюся дати трохи більше ясності в цьому огляді різних прив’язок лібмагічних. Раніше мамадорі дав коротку відповідь, перелічивши доступний варіант.

лібмагічний

Визначаючи файли mime-типу, інструмент вибору просто називається fileі називається його зворотним libmagic. (Див. Домашню сторінку проекту .) Проект розроблений у приватному cvs-сховищі, але на github є дзеркало для читання лише для читання .

Тепер цей інструмент, який вам знадобиться, якщо ви хочете використовувати будь-яке з лібмагічних прив'язок з python, уже поставляється з власними прив'язками python file-magic. Існує не так багато присвячених документацій для них, але ви завжди можете подивитися на людей сторінці з-бібліотеці: 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. Це згадується лише мамадорі, і жодної іншої відповіді це не використовує.


7

Метод @toivotuo працював найкраще і надійніше для мене під python3. Моєю метою було визначити gzipped файли, які не мають надійного розширення .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))

для файлу gzipped він повертає: application / gzip; charset = двійковий

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

для файлу tar: application / x-tar; charset = двійковий

для файлу bz2: application / x-bzip2; charset = двійковий

і останнє, але не менш важливе для мене .zip-файл: application / zip; charset = двійковий


7

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

mimetypes.guess_type (URL, строгий = True) Відгадайте тип файлу на основі його імені файлу чи URL-адреси, заданої URL-адресою. Зворотне значення - кортеж (тип, кодування), де тип - None, якщо тип не вдається відгадати (відсутній або невідомий суфікс) або рядок форми "type / subtype", який можна використовувати для заголовка типу вмісту MIME.

кодування є None для жодного кодування або назви програми, що використовується для кодування (наприклад, стиснення або gzip). Кодування підходить для використання як заголовка контенту вмісту, а не як заголовка контенту перенесення-кодування. Відображення відображається в таблиці. Суфікси кодування залежать від регістру; Суфікси типу спершу спробуються в регістрі чутливо, потім бувають нечутливими.

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

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

6

Ви не вказали, яким веб-сервером користуєтесь, але Apache має гарний маленький модуль під назвою Mime Magic, який він використовує для визначення типу файлу, коли йому сказано про це. Він читає частину вмісту файлу і намагається з'ясувати, для якого типу він заснований на знайдених символах. І як згадав Дейв Вебб про модуль MimeTypes під пітона буде працювати, якщо розширення зручно.

Крім того, якщо ви сидите на коробці UNIX, ви можете скористатися sys.popen('file -i ' + fileName, mode='r')типом MIME. У Windows повинна бути рівнозначна команда, але я не впевнений, що це таке.


7
Сьогодні ви можете просто зробити subprocess.check_output (['файл', '-b', '--ime', ім'я файлу])
Nathan Villaescusa

Дійсно немає причин вдаватися до використання зовнішнього інструменту, коли python-magic робить рівнозначну річ, все загорнене та затишне.
чорт

4

У 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) Дякую!
Клод COULOMBE

3

Спершу спробую бібліотеку міметипів Якщо це не працює, я замість цього використовую пітон-магічну лібарію.

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

1

Модуль mimetypes просто розпізнає тип файлу на основі розширення файлу. Якщо ви спробуєте відновити тип файлу без розширення, миметипи не будуть працювати.


3
Я не думаю, що це правда. Тип MIME - це те, як розповісти іншим про формат даних, а не про те, як самостійно дізнатися формат даних. Якщо ви використовуєте інструмент, який відгадує формат лише на основі розширення та роздруковує типи MIME, тоді ви не можете використовувати цей інструмент, якщо немає розширень файлів. Але можливі й інші способи відгадати формат, наприклад, перевіривши парсер.
erikbwork

1

Я здивований, що ніхто про це не згадував, але Pygments здатний зробити так, щоб вони здогадувалися про тип mime-типу, зокрема, текстових документів.

Pygments - насправді бібліотека виділення синтаксису Python, але це метод, який дозволить зрозуміти, з яких 500 підтримуваних типів документів знаходиться ваш документ. тобто c ++ проти C # проти 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 форматів документів використовується, це дуже корисно.


0

Я намагався багато прикладів , але з Django мутаген грає добре.

Приклад перевірки наявності файлів mp3

from mutagen.mp3 import MP3, HeaderNotFoundError  

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

Мінусом є те, що ваша можливість перевірки типів файлів обмежена, але це чудовий спосіб, якщо ви хочете не тільки перевірити тип файлу, але й отримати додаткову інформацію.


Мені також потрібно перевірити безпеку
Артем Бернацький


0

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


-1

ви можете використовувати модуль imghdr Python.


1
Це не корисний коментар, оскільки він не наводить прикладів і не говорить насправді, як або чому imghdr допоможе тут.
erikbwork

2
Так, я це розумію. Минуло рік тому, але, можливо, ви все ще можете його оновити, оскільки все ще є люди, які шукають це питання, як я. Якщо вам потрібна допомога, ви можете мені сказати.
erikbwork

1
Він працює лише для дуже обмеженого списку типів зображень.
Поняття
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.