Как проверить формат изображения в django ImageField
наш проект использует Python 2.7, PIL 1.1.7 и Django 1.5.1. Существует ImageField, который работает нормально для многих форматов изображений, включая bmp, gif, ico, pnm, psd, tif и pcx. Однако требование состоит в том, чтобы разрешить только изображения png или jpg. Как это можно сделать?
Upd. Я знаю,что могу проверить расширение файла и заголовок HTTP Content-Type. Но ни один из методов не надежен. Я спрашиваю, есть ли способ проверить содержимое загруженного файла на png/jpg.
3 ответов
вы не указываете, используете ли вы форму Django для загрузки изображения, я предполагаю, что в поле формы выполняется проверка.
что вы можете сделать, это создать подкласс django.forms.fields.ImageField
для расширения функциональности to_python.
проверка типа файла в настоящее время выполняется в Django в to_python
выглядит так
Image.open(file).verify()
ваш подкласс может выглядеть примерно так.
class DmitryImageField(ImageField):
def to_python(self, data):
f = super(DmitryImageField, self).to_python(data)
if f is None:
return None
try:
from PIL import Image
except ImportError:
import Image
# We need to get a file object for PIL. We might have a path or we might
# have to read the data into memory.
if hasattr(data, 'temporary_file_path'):
file = data.temporary_file_path()
else:
if hasattr(data, 'read'):
file = BytesIO(data.read())
else:
file = BytesIO(data['content'])
try:
im = Image.open(file)
if im.format not in ('BMP', 'PNG', 'JPEG'):
raise ValidationError("Unsupport image type. Please upload bmp, png or jpeg")
except ImportError:
# Under PyPy, it is possible to import PIL. However, the underlying
# _imaging C module isn't available, so an ImportError will be
# raised. Catch and re-raise.
raise
except Exception: # Python Imaging Library doesn't recognize it as an image
raise ValidationError(self.error_messages['invalid_image'])
if hasattr(f, 'seek') and callable(f.seek):
f.seek(0)
return f
вы можете заметить, что это большая часть код ImageField.to_python
и может предпочесть просто создать подкласс FileField для использования вместо ImageField
а не подклассы ImageField
и дублирование большей части его функциональности. В этом случае обязательно добавьте im.verify()
перед проверкой формата.
EDIT: я должен отметить, что я не тестировал этот подкласс.
вы, вероятно, захотите использовать os для этого. Из документов Python.
os.путь.splitext(путь) Разделите путь пути на пару (root, ext) таким образом, что root + ext == path, а ext пуст или начинается с точки и содержит не более одного периода. Начальные периоды базового имени игнорируются; splitext ('.cshrc') returns ('.cshrc по', "). Изменено в версии 2.6: более ранние версии могли создать пустой корень, когда единственным периодом был первый характер.
пример
import os
fileName, fileExtension = os.path.splitext('yourImage.png')
print fileName
>>> "yourImage"
print fileExtension
>>> ".png"
поэтому, как только вы отделите ext от имени файла, вы должны просто использовать простое сравнение строк, чтобы убедиться, что это правильный формат.
можно использовать python-magic, оболочка ctype вокруг libmagic, библиотеки, используемой file
на Linux.
из его doc:
>>> import magic
>>> magic.from_file("testdata/test.pdf")
'PDF document, version 1.2'
>>> magic.from_buffer(open("testdata/test.pdf").read(1024))
'PDF document, version 1.2'
>>> magic.from_file("testdata/test.pdf", mime=True)
'application/pdf'
однако этот метод просто посмотрите на mime
информация. Вы все еще можете загрузить недействительный PNG с правильным mime
или встроить несанкционированные данные в метаданные файла.