Python'da bir dosyanın mime türü nasıl bulunur?


194

Diyelim ki bir grup dosyayı bir yere, örneğin BLOB'lara kaydetmek istiyorsunuz. Diyelim ki bu dosyaları bir web sayfası üzerinden temizlemek ve istemcinin otomatik olarak doğru uygulamayı / görüntüleyiciyi açmasını istiyorsunuz.

Varsayım: Tarayıcı, HTTP yanıtında mime tipi (içerik tipi?) Başlığı tarafından hangi uygulamanın / görüntüleyicinin kullanılacağını belirler.

Bu varsayımı temel alarak, dosyanın baytlarına ek olarak, MIME türünü de kaydetmek istersiniz.

Bir dosyanın MIME türünü nasıl buldunuz? Şu anda bir Mac kullanıyorum, ancak bu Windows'ta da çalışmalıdır.

Tarayıcı, dosyayı web sayfasına gönderirken bu bilgileri ekliyor mu?

Bu bilgiyi bulmak için düzgün bir python kütüphanesi var mı? WebServis veya (daha da iyisi) indirilebilir bir veritabanı mı?

Yanıtlar:


218

Toivotuo tarafından önerilen python-magic yöntemi eskidir. Python- magic'in şu anki gövdesi Github'da ve oradaki benioku temelli, MIME tipini bulmak bu şekilde yapılıyor.

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

17
yorum için teşekkürler! "yukarıda" ifadesinin yığın akışı içinde zor bir kavram olduğunu lütfen unutmayın, çünkü sıralama oylara göre gruplandırılmış ve gruplar içinde rastgele sıralanmıştır. Sanırım @ toivotuo'nun cevabına bakıyorsun.
Daren Thomas

1
Evet, bu cevabı yazarken yorum yapmak için yeterli "puanım" yoktu. Ama muhtemelen bir yorum olarak yazmalıydım, böylece @toivotuo sorusunu düzenleyebilirdi.
Simon Zimmermann

1
rpm -qf /usr/lib/python2.7/site-packages/magic.py -i URL: darwinsys.com/file Özet: libmagic API için python bağlamaları rpm -qf / usr / bin / file -i Ad: dosya URL: darwinsys.com/file gelen piton-sihirli darwinsys.com/file en söyleyen toivotuo ve Linux Fedora ile gelir @ gibi çalışır. Ve daha ana akım gibi görünüyor.
Sérgio

7
Python-magic adlı debian / ubuntu paketinin aynı isimdeki pip paketinden farklı olduğuna dikkat edin. Her ikisi import magicde uyumsuz içeriğe sahipler. Daha fazla bilgi için stackoverflow.com/a/16203777/3189 adresine bakın .
Hamish Downer

1
Toivotuo'nun cevabına yorum yaptığım gibi, modası geçmiş değil! Farklı bir kütüphane hakkında konuşuyorsunuz. Cevabınızdaki bu ifadeyi kaldırabilir veya değiştirebilir misiniz? Şu anda en iyi çözümü bulmayı gerçekten zorlaştırıyor.
bodo

87

Mimetypes modülü / belirlemek dosya uzantısından MIME türü tahmin edecek standart kütüphanede.

Kullanıcılar dosya yüklüyorsa, HTTP yayını verilerin yanında dosyanın MIME türünü içerir. Örneğin, Django bu verileri UploadedFile nesnesinin bir özniteliği olarak kullanılabilir hale getirir .


12
Dosyalar, soruda belirtildiği gibi BLOB'larda depolanıyorsa, dosya uzantısını bilmiyor olabilirsiniz.
Mekanik salyangoz

55
Dosya uzantıları mime türünü belirlemenin güvenilir bir yolu değildir.
Cerin

13
import mimetypes mimetypes.MimeTypes().guess_type(filename)[0]
Jonathan

4
3.6'da çalışır:mimetypes.guess_type(path_file_to_upload)[1]
JinSnow

3
@Cerin, dosya uzantılarının güvenilir olmadığı python-magickonusunda doğru olsa da, github.com/s3tools/s3cmd/issues/198 tarafından onaylandığı gibi , (üst yanıtta önerildiği gibi) doğruluğunun daha da düşük olduğunu keşfettim . Yani, mimetypesbenim için daha iyi bir aday gibi görünüyor.
Danqing

46

Mimetypes kütüphanesini kullanmaktan daha güvenilir bir yol, python-magic paketini kullanmak olacaktır.

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

Bu, dosya (1) kullanılmasına eşdeğerdir.

Django'da MIME türünün UploadedFile.content_type türüyle eşleştiğinden de emin olabilirsiniz.


2
Python-
magic'in

@DarenThomas: Mammadori'nin cevabında belirtildiği gibi, bu cevap eski ve Simon Zimmermann'ın çözümünden farklı değil . Dosya yardımcı programı yüklüyse, muhtemelen bu çözümü kullanabilirsiniz. Benim için dosya-5.32 ile çalışıyor. Gentoo'da ayrıca dosya paketi için python USE bayrağını etkinleştirmeniz gerekir.
bodo

36

Bu çok kolay görünüyor

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

Lütfen Eski Gönderiye bakın

Güncelleme - @Garrets yorumuna göre, python 3'te daha basit:

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

4
Örneğinizde urllib'in gerekli olduğunu sanmıyorum.
BrotherJack

5
Python 3.X için import urllib yerine urllib import isteğini kullanın. Ve sonra urllib yerine "istek" kullanın
Arjun Thakur

1
Python 2.7 için de çalışıyor
Jay Modi

@ oetzi'nin çözümü bu modülü kullanır, ancak daha basittir.
Garrett

11

Libmagic'i saran 3 farklı kütüphane vardır.

Bunlardan 2 tanesi pypi'de mevcuttur (bu nedenle pip kurulumu çalışır):

  • filemagic
  • piton-büyü

Python-magic'e benzeyen bir diğeri doğrudan en son libmagic kaynaklarında mevcuttur ve muhtemelen linux dağıtımınızda olan kaynaktır.

Debian'da python-magic paketi bununla ilgilidir ve toivotuo'nun söylediği gibi kullanılır ve Simon Zimmermann'ın (IMHO) dediği gibi kullanılmaz.

Bana başka bir yaklaşım gibi görünüyor (orijinal libmagic yazarı tarafından).

Çok kötü doğrudan pypi üzerinde mevcut değildir.


Kolaylık için bir repo ekledim: github.com/mammadori/magic-python bu şekilde yapabilirsiniz:pip install -e git://github.com/mammadori/magic-python.git#egg=Magic_file_extensions
mammadori

10

Python 2.6'da:

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

6
Bu gereksizdir, çünkü filekomut temel olarak libmagic etrafındaki bir pakettir. Simon'un cevabında olduğu gibi sadece python bağlamasını da (python-magic) kullanabilirsiniz.
Mekanik salyangoz

6
Bu işletim sistemine bağlıdır. Mac OS X'te, örneğin, "dosyanız" var ancak normal ortamda libmagic yok.
rptb1

9

2017 Güncellemesi

Github'a gitmeye gerek yok, farklı bir adla PyPi'de:

pip3 install --user python-magic
# or:
sudo apt install python3-magic  # Ubuntu distro package

Kod da basitleştirilebilir:

>>> import magic

>>> magic.from_file('/tmp/img_3304.jpg', mime=True)
'image/jpeg'

js veya css dosyası için de aynısını yapabilir misiniz?
kumbhanibhavesh

Tabii neden olmasın??
Gringo Suave

9

Libmagic'e Python bağları

Bu konudaki tüm farklı cevaplar çok kafa karıştırıcı, bu yüzden libmagic'in farklı bağlarına genel bakış ile biraz daha açıklık vermeyi umuyorum. Daha önce mammadori , mevcut seçeneği listeleyen kısa bir cevap verdi .

Libmagic

Mime tipi bir dosya belirlenirken, seçim aracı basitçe çağrılır fileve arka ucu çağrılır libmagic. (Bkz. Proje ana sayfası .) Proje özel bir cvs deposunda geliştirildi, ancak github'da salt okunur bir git aynası var .

Python ile herhangi bir libmagic bağlamayı kullanmak istiyorsanız ihtiyacınız olacak bu araç, zaten kendi python bağlamaları ile birlikte geliyor file-magic. Orada onlar için çok özel belgeler değil, ama her zaman c-kütüphane adam sayfasına bir göz olabilir: man libmagic. Temel kullanım benioku dosyasında açıklanmıştır :

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)

Bunun dışında , örnek dosyada gösterildiği gibi Magickullanarak bir nesne oluşturarak kitaplığı da kullanabilirsiniz .magic.open(flags)

Hem toivotuo hem de ewr2san , alette bulunan bu file-magicbağları kullanır file. Yanlışlıkla python-magicpaketi kullandıklarını varsayıyorlar . Bu, hem fileve hem python-magicde kurulu ise, python modülünün öncekine magicatıfta bulunduğunu gösterir.

piton-büyü

Bu, Simon Zimmermann'ın cevabında bahsettiği ve Claude COULOMBE ve Gringo Suave tarafından da kullanılan kütüphane .

filemagic

Not : Bu proje en son 2013 yılında güncellendi!

Aynı c-api'ye dayandığı için, bu kütüphane file-magiciçeriyor libmagic. Sadece mammadori tarafından bahsedilir ve başka hiçbir cevap bunu kullanmaz.


7

@toivotuo'nun yöntemi python3 altında benim için en iyi ve en güvenilir şekilde çalıştı. Amacım, güvenilir bir .gz uzantısı olmayan gzip dosyaları tanımlamaktı. Python3-magic yükledim.

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

bir gzip dosya için şunu döndürür: application / gzip; charset = ikili

sıkıştırılmamış bir txt dosyası için (iostat verileri): metin / düz; charset = us-ascii

tar dosyası için: application / x-tar; charset = ikili

bz2 dosyası için: application / x-bzip2; charset = ikili

ve son fakat benim için önemli olmayan bir .zip dosyası: application / zip; charset = ikili


7

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

mimetypes.guess_type (url, strict = True) URL tarafından verilen dosya adını veya URL'sini temel alarak bir dosyanın türünü tahmin edin. Dönüş değeri, tür tahmin edilemiyorsa (eksik veya bilinmeyen sonek) veya MIME içerik türü üstbilgisi için kullanılabilen 'type / subtype' biçiminde bir dize olan türün Yok olduğu bir demettir (tür, kodlama).

kodlama, kodlama veya kodlamak için kullanılan programın adı (ör. sıkıştır veya gzip) için Yok'tur. Kodlama, Content-Transfer-Encoding üstbilgisi olarak değil, Content-Encoding üstbilgisi olarak kullanım için uygundur. Eşlemeler tablo ile yürütülür. Kodlama sonekleri büyük / küçük harfe duyarlıdır; tip son ekleri önce büyük / küçük harfe duyarlı bir şekilde, daha sonra büyük / küçük harfe duyarsızca denenir.

İsteğe bağlı katı argüman, bilinen MIME türleri listesinin yalnızca IANA'ya kayıtlı resmi türlerle sınırlı olup olmadığını belirten bir işarettir. Katı doğruysa (varsayılan), yalnızca IANA türleri desteklenir; katı Yanlış olduğunda, bazı ek standart olmayan ancak yaygın olarak kullanılan MIME türleri de tanınır.

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

6

Hangi web sunucusunu kullandığınızı belirtmediniz, ancak Apache, Mime Magic adında güzel bir modül içeriyor. Dosyanın içeriğinin bir kısmını okur ve bulunan karakterlere dayanarak ne tür bir dosya olduğunu anlamaya çalışır. Ve Dave Webb , Python altındaki MimeTypes Modülünden bahsettiği gibi , bir uzantı kullanışlı olduğu sürece çalışacaktır.

Alternatif olarak, bir UNIX kutusunda oturuyorsanız sys.popen('file -i ' + fileName, mode='r'), MIME türünü almak için kullanabilirsiniz. Windows'un eşdeğer bir komutu olmalı, ancak ne olduğundan emin değilim.


7
Bugünlerde subprocess.check_output (['file', '-b', '--mime', dosya adı])
Nathan Villaescusa

Python-magic eşdeğer bir şey yaptığında harici bir araç kullanmaya başvurmak için hiçbir neden yoktur, hepsi sarılmış ve rahat.
DAMD

4

Python 3.x ve webapp içinde url ile bir uzantısı veya sahte uzantısı olamazdı dosya. Kullanarak python-magic yüklemelisiniz

pip3 install python-magic

Mac OS X için, libmagic yazılımını kullanarak

brew install libmagic

Kod pasajı

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)

alternatif olarak okumaya bir boyut koyabilirsiniz

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)

Tüm dosyayı yükleyecek mi?
凡 凡

Hayır, bu bir akış, yani normalde sadece birkaç bayt.
Claude COULOMBE

Response.readline () veya response.read (128) tarafından düzenledim Teşekkür ederim!
Claude COULOMBE

3

Önce mimetypes kütüphanesini deniyorum. Çalışmıyorsa, bunun yerine python-magic libary kullanıyorum.

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 modülü dosya uzantısına göre sadece bir dosya türünü tanır. Uzantısı olmayan bir dosya türünü kurtarmayı denerseniz, mime türleri çalışmaz.


3
Bunun doğru olduğunu düşünmüyorum. MIME türü, veri formatını kendiniz nasıl bulacağınızla değil, başkalarına bir veri formatı hakkında nasıl bilgi vereceğinizle ilgilidir. Yalnızca uzantıya göre biçimi tahmin eden ve MIME türlerini yazdıran bir araç kullanırsanız, dosya uzantısı yoksa bu aracı kullanamazsınız. Ancak formatı tahmin etmenin başka yolları da mümkündür, örneğin, bir ayrıştırıcı ile kontrol ederek.
erikbwork

1

Kimsenin bundan bahsetmediğine şaşırdım, ancak Pygments , özellikle metin belgelerinin mim türü hakkında eğitimli bir tahminde bulunabilir.

Pygments aslında bir Python sözdizimi vurgulama kitaplığıdır, ancak belgenizin 500 desteklenen belge türünden hangisi hakkında eğitimli bir tahmin yapabilecek bir yöntemi vardır. yani c ++ vs C # vs Python vs 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)

Çıktı:

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

Şimdi, mükemmel değil, ancak 500 belge biçiminden hangisinin kullanıldığını söyleyebilmeniz gerekiyorsa, bu oldukça yararlıdır.


0

Ben birçok örnek denedim ama Django mutagen ile güzel oynuyor.

Dosyaların mp3

from mutagen.mp3 import MP3, HeaderNotFoundError  

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

Dezavantajı, dosya türlerini kontrol etme yeteneğinizin sınırlı olmasıdır, ancak sadece dosya türünü kontrol etmek değil, aynı zamanda ek bilgilere erişmek için de harika bir yoldur.


Ben de güvenliği kontrol etmek gerekir
Artem Bernatskyi



-1

imghdr Python modülünü kullanabilirsiniz .


1
Bu yararlı bir yorum değildir, çünkü örnek vermez ve imghdr'ın burada nasıl veya neden yardımcı olacağını gerçekten söylemez.
erikbwork

2
Evet bunu anladım. Bir yıldan uzun bir süre önce ama belki de güncelleyebilirsiniz, çünkü hala benim gibi bu soruyu arayan insanlar var. Yardıma ihtiyacınız olursa bana söyleyebilirsiniz.
erikbwork

1
Yalnızca çok sınırlı bir görüntü türü listesi için çalışır. Metin dosyaları, sıkıştırılmış arşivler, belge formatları vb. Hakkında hiçbir fikri yoktur.
tripleee
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.