Загрузка изображения Django…Предотвращение загрузки огромных файлов

#django #file #django-models #file-upload

#django #файл #django-модели #загрузка файла

Вопрос:

Мой сайт полагается на загруженные пользователем файлы изображений. Я хочу ограничить max_upload_size.

Я знаю, что вы можете установить FILE_UPLOAD_MAX_MEMORY_SIZE в settings.py . Если загружается файл большего размера, чем этот, он записывается на диск в каталоге tmp. Это в значительной степени обрабатывает вещи? Будут ли огромные изображения по-прежнему влиять на производительность моего сайта вообще?

Одна из альтернатив, которую я видел, — настроить max_upload_size в apache, который (кажется) содержится в php.ini. Это правильно звучит? Целесообразно ли это?

Другой шаг включает проверку атрибутов файлового объекта. Я просмотрел этот снипет (http://djangosnippets.org/snippets/1303 /), который представляет метод проверки формы.

 def clean_content(self):
   content = self.cleaned_data['content']
   content_type = content.content_type.split('/')[0]
    if content_type in settings.CONTENT_TYPES:
       if content._size > settings.MAX_UPLOAD_SIZE:
          raise forms.ValidationError(_('Please keep filesize under %s. Current filesize %s') % (filesizeformat(settings.MAX_UPLOAD_SIZE), filesizeformat(content._size)))
    else:
        raise forms.ValidationError(_('File type is not supported'))
    return content
  

Потенциальные проблемы здесь заключаются в том, что

1) этот код применяется к FileField, а не к ImageField. Я знаю, что ImageField относится к подклассу FileField, поэтому я предполагаю, что это не проблема. Это правда?

2) Весь запрос HttpRequest считывается перед проверкой (поэтому огромные файлы все равно будут проблемой). Кроме того, файл все еще записывается в tmp, даже если он выдает ошибку проверки?

Наконец, вы также заметите, что при проверке формы выполняется фильтрация по типам контента. Я предполагаю, что это в основном бесполезно, поскольку это просто просмотр расширений, которые можно легко подделать. Это тоже справедливо?

Я знаю, что этот вопрос немного бессвязный, но это сложная и неоднозначная тема (по крайней мере, для меня)

Ответ №1:

Я знаю, что вы можете установить FILE_UPLOAD_MAX_MEMORY_SIZE в settings.py . Если загружается файл большего размера, чем этот, он записывается на диск в каталоге tmp. Это в значительной степени обрабатывает вещи? Будут ли огромные изображения по-прежнему влиять на производительность моего сайта вообще?

Зависит от того, что вы подразумеваете под «обработкой». Это не позволит процессу, обрабатывающему загрузку, считывать весь файл в память и использовать ресурсы вашего сервера. Загрузка все равно будет успешной, и вы по-прежнему будете сохранять «большой» файл. Я бы подумал, что это может повлиять на производительность вашего сайта, потому что вы собираетесь связать серверный процесс с загрузкой, которая займет больше времени, поскольку она попадет на диск, что происходит относительно медленно.

Одна из альтернатив, которую я видел, — настроить max_upload_size в apache, который (кажется) содержится в php.ini. Это правильно звучит? Целесообразно ли это?

В apache есть способ ограничить размер запроса, но это не с помощью этого параметра. Все, что есть в php.ini, специфично для PHP и не имеет отношения к Django. Вы ищете директиву apache LimitRequestBody.

Вопрос здесь в том, чего вы хотите достичь. Вы хотите ограничить размер файлов, хранящихся на вашем сайте, но вам все равно, загружены ли они на самом деле (вас не беспокоит использование вашей полосы пропускания)? Если это так, то вы можете пойти по пути проверки формы, чтобы предоставлять своим пользователям более приятные ошибки.

Однако, если вас действительно волнует пропускная способность, используемая при больших загрузках, и вы хотите остановить загрузку любого файла размером в n МБ, тогда вам следует рассмотреть возможность использования чего-то вроде этого QuotaUploadHandler или установки ограничения через ваш веб-сервер (см. LimitRequestBody выше). Если вы используете обработчик загрузки, вам нужно будет протестировать поведение при возникновении исключения StopUpload — об этом есть небольшой комментарий в методе «receive_data_chunk» в документах по загрузке файлов. Если вы решите разрешить apache останавливать загрузку после определенного размера, вы, вероятно, в конечном итоге покажете несколько довольно уродливых страниц ошибок своим пользователям, которые превысят этот лимит.

Комментарии:

1. Привет, shadfc, это был отличный ответ. Я не смог найти LimitRequestBody. Я думаю, что я буду использовать проверку формы до определенного размера, а затем внедрю LRB для невероятно больших файлов.

2. @brendan: это, наверное, лучше всего. Я быстро протестировал этот QuotaUploadHandler и, похоже, не существует способа обрабатывать ошибки, вызванные этим — вы просто получаете ошибку сброса соединения. Поэтому, вероятно, лучше всего позволить apache обрабатывать огромные файлы, потому что они получат более конкретное сообщение об ошибке. Очень жаль, что для этой функциональности вам приходится подключаться к веб-серверу. Было бы здорово справиться с этим в Django с ошибками формы, но это, вероятно, несбыточная мечта.

Ответ №2:

Попробуйте приведенный ниже код,

 from django.core.exceptions import ValidationError
def validate_image(fieldfile_obj):
        filesize = fieldfile_obj.file.size
        megabyte_limit = 2.0
        if filesize > megabyte_limit*1024*1024:
            raise ValidationError("Max file size is %sMB" % str(megabyte_limit))

class User(models.Model):
    avatar = models.ImageField("Avatar", upload_to=upload_logo_to,validators=[validate_image], blank=True, null=True,help_text='Maximum file size allowed is 2Mb')