كيفية العثور على نوع mime للملف في بيثون؟
سؤال
لنفترض أنك تريد حفظ مجموعة من الملفات في مكان ما، على سبيل المثال في BLOBs.لنفترض أنك تريد توزيع هذه الملفات عبر صفحة ويب وجعل العميل يفتح تلقائيًا التطبيق/العارض الصحيح.
افتراض:يحدد المتصفح التطبيق/العارض الذي سيتم استخدامه من خلال رأس نوع mime (نوع المحتوى؟) في استجابة HTTP.
بناءً على هذا الافتراض، بالإضافة إلى بايتات الملف، فإنك تريد أيضًا حفظ نوع MIME.
كيف يمكنك العثور على نوع MIME للملف؟أستخدم حاليًا جهاز Mac، ولكن من المفترض أن يعمل هذا أيضًا على نظام Windows.
هل يضيف المتصفح هذه المعلومات عند نشر الملف على صفحة الويب؟
هل هناك مكتبة بيثون أنيقة للعثور على هذه المعلومات؟خدمة ويب أو (حتى أفضل) قاعدة بيانات قابلة للتنزيل؟
المحلول
إن طريقة سحر الثعبان التي اقترحها toivotuo قديمة. بايثون ماجيك الجذع الحالي موجود في Github واستنادًا إلى الملف التمهيدي هناك، يتم العثور على نوع MIME على هذا النحو.
# For MIME types
>>> import magic
>>> mime = magic.Magic(mime=True)
>>> mime.from_file("testdata/test.pdf")
'application/pdf'
>>>
نصائح أخرى
ال وحدة أنواع mimetypes في المكتبة القياسية سيحدد/يخمن نوع MIME من امتداد الملف.
إذا كان المستخدمون يقومون بتحميل الملفات، فسوف يحتوي منشور HTTP على نوع MIME للملف إلى جانب البيانات.على سبيل المثال، يجعل Django هذه البيانات متاحة كسمة للملف تم تحميل الملف هدف.
الطريقة الأكثر موثوقية من استخدام مكتبة mimetypes هي استخدام حزمة python-magic.
import magic
m = magic.open(magic.MAGIC_MIME)
m.load()
m.file("/tmp/document.pdf")
سيكون هذا معادلاً لاستخدام الملف (1).
في Django، يمكن للمرء أيضًا التأكد من أن نوع MIME يطابق نوع UploadedFile.content_type.
يبدو أن هذا سهل للغاية
>>> 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)
يرجى الرجوع مشاركة قديمة
هناك 3 مكتبات مختلفة تغلف libmagic.
يتوفر 2 منها على pypi (لذلك سيعمل تثبيت pip):
- filemagic
- بيثون السحر
ويوجد خيار آخر مشابه لـ python-magic وهو متاح مباشرةً في أحدث مصادر libmagic، وهو على الأرجح موجود في توزيعة Linux الخاصة بك.
في دبيان، الحزمة python-magic تدور حول هذا الموضوع ويتم استخدامها كما قال toivotuo ولم تعد قديمة كما قال سيمون زيمرمان (IMHO).
يبدو لي أن هذا أمر آخر (من قبل المؤلف الأصلي لـ libmagic).
سيء للغاية غير متوفر مباشرة على pypi.
في بيثون 2.6:
mime = subprocess.Popen("/usr/bin/file --mime PATH", shell=True, \
stdout=subprocess.PIPE).communicate()[0]
لم تذكر ما هو خادم الويب الذي تستخدمه، ولكن لدى Apache وحدة صغيرة لطيفة تسمى ميمي ماجيك والذي يستخدمه لتحديد نوع الملف عندما يُطلب منه ذلك.يقرأ بعض محتوى الملف ويحاول معرفة نوعه بناءً على الأحرف الموجودة.و كما ذكر ديف ويب ال وحدة MimeTypes سيعمل تحت python، بشرط أن يكون الامتداد مفيدًا.
وبدلاً من ذلك، إذا كنت تجلس على صندوق UNIX يمكنك استخدامه sys.popen('file -i ' + fileName, mode='r')
للاستيلاء على نوع MIME.يجب أن يكون لدى Windows أمر مكافئ، لكنني غير متأكد من ماهيته.
عملت طريقة @ 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))
بالنسبة للملف المضغوط بصيغة gzipped، فإنه يُرجع:التطبيق / غزيب؛مجموعة الأحرف = ثنائي
لملف txt غير مضغوط (بيانات iostat):نص عادي؛مجموعة الأحرف=us-ascii
لملف القطران:التطبيق/x-القطران؛مجموعة الأحرف = ثنائي
لملف bz2:التطبيق/x-bzip2;مجموعة الأحرف = ثنائي
وأخيرًا وليس آخرًا بالنسبة لي ملف .zip:التطبيق/الرمز البريدي؛مجموعة الأحرف = ثنائي
في 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)
تحديث 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'
روابط بايثون إلى libmagic
جميع الإجابات المختلفة حول هذا الموضوع مربكة للغاية، لذلك آمل أن أقدم المزيد من الوضوح من خلال هذه النظرة العامة على الارتباطات المختلفة لـ libmagic.في السابق أعطى مامادوري أ اجابة قصيرة سرد الخيار المتاح.
libmagic
- اسم وحدة:
magic
- بيبي: file-magic
- مصدر: https://github.com/file/file/tree/master/python
عند تحديد نوع الملفات الصامتة، يتم استدعاء الأداة المفضلة ببساطة file
وتسمى نهايته الخلفية libmagic
.(انظر الصفحة الرئيسية للمشروع.) تم تطوير المشروع في مستودع سيرة ذاتية خاص، ولكن هناك مرآة جيت للقراءة فقط على جيثب.
الآن هذه الأداة، التي ستحتاجها إذا كنت تريد استخدام أي من روابط libmagic مع python، تأتي بالفعل مع روابط python الخاصة بها والتي تسمى file-magic
.لا يوجد الكثير من الوثائق المخصصة لها، ولكن يمكنك دائمًا إلقاء نظرة على صفحة الدليل الخاصة بالمكتبة c: man libmagic
.تم وصف الاستخدام الأساسي في الملف التمهيدي:
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)
كما هو مبين في ملف المثال.
كلاهما com.toivotuo وewr2san استخدم هذه file-magic
الارتباطات المدرجة في file
أداة.إنهم يفترضون خطأً أنهم يستخدمون python-magic
طَرد. ويبدو أن هذا يشير إلى أنه إذا كان كلاهما file
و python-magic
تم تثبيت وحدة بايثون magic
يشير إلى السابق.
بيثون السحر
- اسم وحدة:
magic
- بيبي: بيثون السحر
- مصدر: https://github.com/ahupp/python-magic
هذه هي المكتبة التي يتحدث عنها سيمون زيمرمان إجابته والذي يعمل به أيضًا كلود كولومب إلى جانب جرينجو لطيف.
filemagic
- اسم وحدة:
magic
- بيبي: filemagic
- مصدر: https://github.com/aliles/fimagic
ملحوظة:تم تحديث هذا المشروع آخر مرة في عام 2013!
نظرًا لاستنادها إلى نفس c-api، فإن هذه المكتبة لديها بعض التشابه مع file-magic
متضمن في libmagic
.ولم يذكر إلا من مامادوري ولا توجد إجابة أخرى تستخدمه.
تتعرف وحدة mimetypes على نوع الملف بناءً على امتداد الملف.إذا كنت ستحاول استرداد نوع ملف بدون ملحق، فلن تعمل أنواع mimetypes.
لقد جربت الكثير من الأمثلة ولكن مع Django المطفرة يلعب بشكل جيد.
مثال للتحقق مما إذا كانت الملفات mp3
from mutagen.mp3 import MP3, HeaderNotFoundError
try:
audio = MP3(file)
except HeaderNotFoundError:
raise ValidationError('This file should be mp3')
الجانب السلبي هو أن قدرتك على التحقق من أنواع الملفات محدودة، ولكنها طريقة رائعة إذا كنت لا تريد فقط التحقق من نوع الملف ولكن أيضًا الوصول إلى معلومات إضافية.
قد يكون هذا قديمًا بالفعل، ولكن لماذا لا تستخدم UploadedFile.content_type مباشرةً من Django؟أليس كذلك؟(https://docs.djangoproject.com/en/1.11/ref/files/uploads/#django.core.files.uploadedfile.UploadedFile.content_type)
بالنسبة لبيانات نوع صفيف البايت ، يمكنك استخدام 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
يمكنك استخدام com.imghdr وحدة بايثون.