Wie finde ich den MIME-Typ einer Datei in Python?
Frage
Nehmen wir an, Sie möchten eine Reihe von Dateien irgendwo speichern, beispielsweise in BLOBs.Nehmen wir an, Sie möchten diese Dateien über eine Webseite verteilen und den Client automatisch die richtige Anwendung/den richtigen Viewer öffnen lassen.
Annahme:Der Browser erkennt anhand des Mime-Type-Headers (Content-Type?) in der HTTP-Antwort, welche Anwendung/welcher Viewer verwendet werden soll.
Basierend auf dieser Annahme möchten Sie zusätzlich zu den Bytes der Datei auch den MIME-Typ speichern.
Wie finden Sie den MIME-Typ einer Datei?Ich verwende derzeit einen Mac, aber das sollte auch unter Windows funktionieren.
Fügt der Browser diese Informationen hinzu, wenn er die Datei auf der Webseite veröffentlicht?
Gibt es eine übersichtliche Python-Bibliothek, um diese Informationen zu finden?Ein WebService oder (noch besser) eine herunterladbare Datenbank?
Lösung
Die von toivotuo vorgeschlagene Python-Magic-Methode ist veraltet. Python-Magie Der aktuelle Trunk befindet sich bei Github und basierend auf der dortigen Readme-Datei wird das Finden des MIME-Typs wie folgt durchgeführt.
# For MIME types
>>> import magic
>>> mime = magic.Magic(mime=True)
>>> mime.from_file("testdata/test.pdf")
'application/pdf'
>>>
Andere Tipps
Der Mimetypes-Modul in der Standardbibliothek ermittelt/errät den MIME-Typ anhand einer Dateierweiterung.
Wenn Benutzer Dateien hochladen, enthält der HTTP-Beitrag neben den Daten auch den MIME-Typ der Datei.Django stellt diese Daten beispielsweise als Attribut des zur Verfügung HochgeladeneDatei Objekt.
Zuverlässiger als die Verwendung der Mimetypes-Bibliothek wäre die Verwendung des Pakets python-magic.
import magic
m = magic.open(magic.MAGIC_MIME)
m.load()
m.file("/tmp/document.pdf")
Dies wäre äquivalent zur Verwendung von Datei(1).
Auf Django könnte man auch sicherstellen, dass der MIME-Typ mit dem von UploadedFile.content_type übereinstimmt.
Das scheint sehr einfach zu sein
>>> 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)
Siehe Alter Beitrag
Es gibt 3 verschiedene Bibliotheken, die libmagic umschließen.
2 davon sind auf Pypi verfügbar (damit die Pip-Installation funktioniert):
- filemagic
- Python-Magie
Und ein anderes, ähnlich wie python-magic, ist direkt in den neuesten libmagic-Quellen verfügbar, und es ist das, was Sie wahrscheinlich in Ihrer Linux-Distribution haben.
In Debian handelt es sich um das Paket python-magic, das verwendet wird, wie toivotuo sagte, und es ist nicht veraltet, wie Simon Zimmermann sagte (IMHO).
Es scheint mir eine andere Einstellung zu sein (vom ursprünglichen Autor von libmagic).
Schade, dass es nicht direkt auf Pypi verfügbar ist.
in Python 2.6:
mime = subprocess.Popen("/usr/bin/file --mime PATH", shell=True, \
stdout=subprocess.PIPE).communicate()[0]
Sie haben nicht angegeben, welchen Webserver Sie verwenden, aber Apache hat ein nettes kleines Modul namens Pantomime-Magie anhand dessen es den Typ einer Datei ermittelt, wenn es dazu aufgefordert wird.Es liest einen Teil des Inhalts der Datei und versucht anhand der gefundenen Zeichen herauszufinden, um welchen Typ es sich handelt.Und wie Dave Webb erwähnt Die MimeTypes-Modul unter Python wird funktionieren, vorausgesetzt, eine Erweiterung ist praktisch.
Wenn Sie auf einem UNIX-Rechner sitzen, können Sie alternativ auch verwenden sys.popen('file -i ' + fileName, mode='r')
um den MIME-Typ zu erfassen.Windows sollte einen entsprechenden Befehl haben, aber ich bin mir nicht sicher, was das ist.
Die Methode von @toivotuo funktionierte für mich unter Python3 am besten und zuverlässigsten.Mein Ziel war es, gzip-Dateien zu identifizieren, die keine zuverlässige .gz-Erweiterung haben.Ich habe Python3-Magic installiert.
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))
Für eine gzip-Datei wird Folgendes zurückgegeben:application/gzip;Zeichensatz=binär
für eine entpackte TXT-Datei (Iostat-Daten):Text/einfach;charset=us-ascii
für eine TAR-Datei:application/x-tar;Zeichensatz=binär
für eine bz2-Datei:application/x-bzip2;Zeichensatz=binär
und zu guter Letzt für mich eine .zip-Datei:Anwendung/zip;Zeichensatz=binär
In Python 3.x und Webapp mit URL zur Datei, die keine Erweiterung oder eine gefälschte Erweiterung haben darf.Sie sollten Python-Magic mit installieren
pip3 install python-magic
Für Mac OS X sollten Sie auch libmagic mit installieren
brew install libmagic
Code-Auszug
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)
Alternativ könnten Sie eine Größe in den Lesevorgang eingeben
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)
Aktualisierung 2017
Sie müssen nicht zu Github gehen, es ist auf PyPi unter einem anderen Namen:
pip3 install --user python-magic
# or:
sudo apt install python3-magic # Ubuntu distro package
Der Code kann auch vereinfacht werden:
>>> import magic
>>> magic.from_file('/tmp/img_3304.jpg', mime=True)
'image/jpeg'
Python-Bindungen an libmagic
Die unterschiedlichen Antworten zu diesem Thema sind sehr verwirrend, daher hoffe ich, mit diesem Überblick über die verschiedenen Bindungen von libmagic etwas mehr Klarheit zu schaffen.Zuvor gab Mammadori eine kurze Antwort Auflistung der verfügbaren Option.
libmagic
- Modulname:
magic
- pypi: Dateimagie
- Quelle: https://github.com/file/file/tree/master/python
Bei der Bestimmung eines Datei-MIME-Typs wird einfach das Tool der Wahl aufgerufen file
und sein Backend heißt libmagic
.(Siehe die Projekthomepage.) Das Projekt wird in einem privaten CVS-Repository entwickelt, es gibt jedoch ein schreibgeschützter Git-Spiegel auf Github.
Nun verfügt dieses Tool, das Sie benötigen, wenn Sie eine der libmagic-Bindungen mit Python verwenden möchten, bereits über eigene Python-Bindungen namens file-magic
.Es gibt nicht viel spezielle Dokumentation für sie, aber Sie können jederzeit einen Blick auf die Manpage der C-Bibliothek werfen: man libmagic
.Die grundlegende Verwendung wird im beschrieben Readme-Datei:
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)
Darüber hinaus können Sie die Bibliothek auch nutzen, indem Sie eine erstellen Magic
Objekt verwenden magic.open(flags)
wie in der gezeigt Beispieldatei.
Beide toivotuo und ewr2san verwenden diese file-magic
Bindungen im Lieferumfang enthalten file
Werkzeug.Sie gehen fälschlicherweise davon aus, dass sie das verwenden python-magic
Paket. Dies scheint darauf hinzudeuten, dass beides der Fall ist file
Und python-magic
installiert sind, das Python-Modul magic
bezieht sich auf ersteres.
Python-Magie
- Modulname:
magic
- pypi: Python-Magie
- Quelle: https://github.com/ahupp/python-magic
Dies ist die Bibliothek, über die Simon Zimmermann spricht seine Antwort und die auch bei beschäftigt ist Claude COULOMBE sowie Gringo Suave.
filemagic
- Modulname:
magic
- pypi: filemagic
- Quelle: https://github.com/aliles/filemagic
Notiz:Dieses Projekt wurde zuletzt im Jahr 2013 aktualisiert!
Da diese Bibliothek auf derselben C-API basiert, weist sie eine gewisse Ähnlichkeit mit auf file-magic
enthalten libmagic
.Es wird nur von erwähnt mammadori und keine andere Antwort verwendet es.
Das Mimetypes-Modul erkennt einen Dateityp lediglich anhand der Dateierweiterung.Wenn Sie versuchen, einen Dateityp ohne Erweiterung wiederherzustellen, funktionieren die Mimetypes nicht.
Ich habe viele Beispiele ausprobiert, aber mit Django mutagen spielt sich gut.
Beispiel für die Überprüfung, ob Dateien vorhanden sind mp3
from mutagen.mp3 import MP3, HeaderNotFoundError
try:
audio = MP3(file)
except HeaderNotFoundError:
raise ValidationError('This file should be mp3')
Der Nachteil besteht darin, dass Sie nur begrenzte Möglichkeiten zur Überprüfung von Dateitypen haben. Dies ist jedoch eine großartige Möglichkeit, wenn Sie nicht nur den Dateityp überprüfen, sondern auch auf zusätzliche Informationen zugreifen möchten.
Das ist vielleicht schon alt, aber warum nicht UploadedFile.content_type direkt aus Django verwenden?Ist nicht das Gleiche?(https://docs.djangoproject.com/en/1.11/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.content_type)
Für Daten von Byte -Array -Typ können Sie Magic.from_Buffer (_byte_array, mime = true) verwenden.
Ich probiere zuerst die Mimetypes-Bibliothek aus.Wenn es nicht funktioniert, verwende ich stattdessen die Python-Magic-Bibliothek.
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
Sie können verwenden imghdr Python-Modul.