2013-12-24 3 views
6

В нашем проекте используются Python 2.7, PIL 1.1.7 и Django 1.5.1. Существует ImageField, который работает нормально для многих форматов изображений, включая bmp, gif, ico, pnm, psd, tif и pcx. Однако требование заключается только в разрешении изображений png или jpg. Как это можно сделать?Как проверить формат изображения в django ImageField

Обновление. Я знаю, что могу проверить расширение файла и HTTP Content-Type. Но ни один из методов не является надежным. Я спрашиваю, есть ли способ проверить загруженное содержимое файла для png/jpg.

+0

Я знаю, что вы можете поместить некоторые подтверждения в настройках своей формы. Я расскажу вам подробности. –

+0

См. Этот [ответ] (http://stackoverflow.com/questions/4853581/django-get-uploaded-file-type-mimetype?answertab=active#tab-top) и этот [link] (https: // docs .djangoproject.ком/ен/DEV/темы/HTTP/закачка файлов/# uploadedfile-объектов). –

ответ

5

Вы не указали, используете ли вы форму 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: Я должен указать, что я не тестировал этот подкласс.

+0

Спасибо! Он работал для меня (с некоторыми небольшими изменениями) – Dmitry

+1

Это попытка ... кроме блока поймает 'raise ValidationError', плюс вы можете сделать это более легко в форме' clean_field'. – nitely

1

Возможно, вы захотите использовать os для этого. Из документов Python.

os.path.splitext (путь) Разделить путь путь в пару (корень, доб) таким образом, что корень + внутр == путь, а внутр пуст или начинается с периодом, и содержит не более одного период , Ведущие периоды в basename игнорируются; splitext ('.cshrc') возвращает ('.cshrc', ''). Изменено в версии 2.6: более ранние версии могут создавать пустой корень, когда единственным периодом был первый символ.

пример

import os 
fileName, fileExtension = os.path.splitext('yourImage.png') 

print fileName 
>>> "yourImage" 

print fileExtension 
>>> ".png" 

Поэтому, как только у вас есть внутр отделено от имени файла вы должны просто использовать простое сравнение строк, чтобы проверить, что это правильный формат.

+1

Спасибо за ответ. Однако я спрашиваю, могу ли я проверить содержимое загруженного файла для png/jpg. Проверка расширения файла ненадежна. Например, я могу переименовать файл bmp в png, а затем загрузить. – Dmitry

+0

oh так больше, чем просто расширение, которое вы хотите удостовериться, что файл - это то, что расширение должно быть содержимым внутри. Извините, я не понял этот вопрос. –

+0

В большинстве случаев достаточно проверить расширение файла! –

1

Вы можете использовать python-magic, обертку ctype вокруг libmagic, библиотеку, используемую file на Linux.

С его документ:

>>> 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 или вставить несанкционированные данные в метаданные файла.

Смежные вопросы