Come trovare il tipo MIME di un file in Python?
Domanda
Supponiamo che tu voglia salvare un gruppo di file da qualche parte, ad esempio nei BLOB.Supponiamo che tu voglia distribuire questi file tramite una pagina Web e fare in modo che il client apra automaticamente l'applicazione/visualizzatore corretto.
Assunzione:Il browser capisce quale applicazione/visualizzatore utilizzare dall'intestazione mime-type (content-type?) nella risposta HTTP.
Sulla base di questo presupposto, oltre ai byte del file, vuoi salvare anche il tipo MIME.
Come troveresti il tipo MIME di un file?Attualmente utilizzo un Mac, ma dovrebbe funzionare anche su Windows.
Il browser aggiunge queste informazioni quando pubblica il file sulla pagina web?
Esiste una libreria Python ordinata per trovare queste informazioni?Un WebService o (meglio ancora) un database scaricabile?
Soluzione
Il metodo python-magic suggerito da toivotuo è obsoleto. La magia di Python il trunk attuale è su Github e in base al file readme lì, trovare il tipo MIME, viene fatto in questo modo.
# For MIME types
>>> import magic
>>> mime = magic.Magic(mime=True)
>>> mime.from_file("testdata/test.pdf")
'application/pdf'
>>>
Altri suggerimenti
IL modulo mimetypes nella libreria standard determinerà/indovinerà il tipo MIME da un'estensione di file.
Se gli utenti stanno caricando file, il post HTTP conterrà il tipo MIME del file insieme ai dati.Ad esempio, Django rende disponibili questi dati come attributo del file File caricato oggetto.
Un modo più affidabile rispetto all'utilizzo della libreria mimetypes sarebbe utilizzare il pacchetto python-magic.
import magic
m = magic.open(magic.MAGIC_MIME)
m.load()
m.file("/tmp/document.pdf")
Ciò equivarrebbe a utilizzare file(1).
Su Django si potrebbe anche assicurarsi che il tipo MIME corrisponda a quello di UploadedFile.content_type.
Questo sembra essere molto facile
>>> 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)
Per favore, riferisci Vecchia posta
Esistono 3 diverse librerie che racchiudono libmagic.
2 di questi sono disponibili su pypi (quindi l'installazione pip funzionerà):
- filemagic
- python-magico
E un altro, simile a python-magic, è disponibile direttamente negli ultimi sorgenti libmagic, ed è quello che probabilmente hai nella tua distribuzione Linux.
In Debian il pacchetto python-magic riguarda questo ed è usato come ha detto toivotuo e non è obsoleto come ha detto Simon Zimmermann (IMHO).
Mi sembra un'altra versione (dell'autore originale di libmagic).
Peccato che non sia disponibile direttamente su pypi.
in Python 2.6:
mime = subprocess.Popen("/usr/bin/file --mime PATH", shell=True, \
stdout=subprocess.PIPE).communicate()[0]
Non hai indicato quale server web stavi utilizzando, ma Apache ha un modulo carino chiamato Magia del mimo che utilizza per determinare il tipo di file quando gli viene detto di farlo.Legge parte del contenuto del file e cerca di capire di che tipo è in base ai caratteri trovati.E come Menzionato Dave Webb IL Modulo MimeType sotto Python funzionerà, a condizione che un'estensione sia a portata di mano.
In alternativa, se sei seduto su una macchina UNIX puoi usare sys.popen('file -i ' + fileName, mode='r')
per acquisire il tipo MIME.Windows dovrebbe avere un comando equivalente, ma non sono sicuro di cosa sia.
Il metodo di @toivotuo ha funzionato meglio e in modo più affidabile per me con Python3.Il mio obiettivo era identificare i file gzippati che non hanno un'estensione .gz affidabile.Ho installato 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))
per un file gzippato restituisce:applicazione/gzip;set di caratteri=binario
per un file txt decompresso (dati iostat):testo/semplice;charset=us-ascii
per un file tar:applicazione/x-tar;set di caratteri=binario
per un file bz2:applicazione/x-bzip2;set di caratteri=binario
e ultimo ma non meno importante per me un file .zip:applicazione/zip;set di caratteri=binario
In Python 3.x e webapp con l'URL del file che non può avere un'estensione o un'estensione falsa.Dovresti installare python-magic, usando
pip3 install python-magic
Per Mac OS X, dovresti installare anche libmagic usando
brew install libmagic
Frammento di codice
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)
in alternativa potresti inserire una dimensione nel file read
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)
Aggiornamento 2017
Non c'è bisogno di andare su github, è su PyPi con un nome diverso:
pip3 install --user python-magic
# or:
sudo apt install python3-magic # Ubuntu distro package
Il codice può anche essere semplificato:
>>> import magic
>>> magic.from_file('/tmp/img_3304.jpg', mime=True)
'image/jpeg'
Collegamenti Python a libmagic
Tutte le diverse risposte su questo argomento sono molto confuse, quindi spero di fare un po’ più di chiarezza con questa panoramica dei diversi legami di libmagic.In precedenza mammadori ha dato a risposta breve elencando l'opzione disponibile.
libmagic
- nome del modulo:
magic
- pipi: file-magia
- fonte: https://github.com/file/file/tree/master/python
Quando si determina il tipo MIME di un file, viene semplicemente chiamato lo strumento scelto file
e viene chiamato il suo back-end libmagic
.(Vedi il Home page del progetto.) Il progetto è sviluppato in un repository cvs privato, ma esiste un file Mirror git di sola lettura su github.
Ora questo strumento, di cui avrai bisogno se desideri utilizzare uno qualsiasi dei collegamenti libmagic con Python, viene già fornito con i propri collegamenti Python chiamati file-magic
.Non c'è molta documentazione dedicata a loro, ma puoi sempre dare un'occhiata alla pagina man della c-library: man libmagic
.L'utilizzo di base è descritto nel file leggimi:
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)
Oltre a questo, puoi anche utilizzare la libreria creando un file Magic
oggetto utilizzando magic.open(flags)
come mostrato nel file di esempio.
Entrambi toivotuo ed ewr2san usali file-magic
attacchi inclusi nel file
attrezzo.Presumono erroneamente di utilizzare il file python-magic
pacchetto. Ciò sembra indicare che se entrambi file
E python-magic
sono installati, il modulo Python magic
si riferisce al precedente.
python-magico
- nome del modulo:
magic
- pipi: python-magico
- fonte: https://github.com/ahupp/python-magic
Questa è la biblioteca di cui parla Simon Zimmermann la sua risposta e che è anche impiegato da Claude COULOMBE così come Gringo Suave.
filemagic
- nome del modulo:
magic
- pipi: filemagic
- fonte: https://github.com/aliles/filemagic
Nota:Questo progetto è stato aggiornato l'ultima volta nel 2013!
Poiché è basata sullo stesso c-api, questa libreria presenta alcune somiglianze con file-magic
incluso in libmagic
.Viene menzionato solo da mammadori e nessun'altra risposta lo utilizza.
Il modulo mimetypes riconosce semplicemente un tipo di file in base all'estensione del file.Se proverai a recuperare un tipo di file senza estensione, i tipi MIME non funzioneranno.
Ho provato molti esempi ma con Django mutageno gioca bene.
Esempio di verifica se i file lo sono mp3
from mutagen.mp3 import MP3, HeaderNotFoundError
try:
audio = MP3(file)
except HeaderNotFoundError:
raise ValidationError('This file should be mp3')
Lo svantaggio è che la tua capacità di controllare i tipi di file è limitata, ma è un ottimo modo se desideri non solo controllare il tipo di file ma anche accedere a informazioni aggiuntive.
Potrebbe essere già vecchio, ma perché non utilizzare UploadedFile.content_type direttamente da Django?Non è lo stesso?(https://docs.djangoproject.com/en/1.11/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.content_type)
Per i dati del tipo di array di byte è possibile utilizzare magic.from_buffer (_Byte_array, mime = true)
Provo prima la libreria dei tipi MIME.Se non funziona, utilizzo invece la libreria 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
Puoi usare imghdr Modulo Python.