Límite de tamaño de carga del archivo Django

Tengo un formulario en mi aplicación django donde los usuarios pueden cargar archivos.
¿Cómo puedo establecer un límite para el tamaño del archivo cargado de modo que si un usuario carga un archivo más grande que mi límite, el formulario no será válido y arrojará un error?

Este código podría ayudar:

# Add to your settings file CONTENT_TYPES = ['image', 'video'] # 2.5MB - 2621440 # 5MB - 5242880 # 10MB - 10485760 # 20MB - 20971520 # 50MB - 5242880 # 100MB 104857600 # 250MB - 214958080 # 500MB - 429916160 MAX_UPLOAD_SIZE = "5242880" #Add to a form containing a FileField and change the field names accordingly. from django.template.defaultfilters import filesizeformat from django.utils.translation import ugettext_lazy as _ from django.conf import settings 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 

Tomado de: Django Snippets: validar por tipo y tamaño del contenido del archivo

Puedes usar este formato de fragmentoChecker. Lo que hace es

  • te permite especificar qué formatos de archivo se pueden cargar.

  • y le permite establecer el límite de tamaño de archivo del archivo que se cargará.

Primero. Cree un archivo llamado formatChecker.py dentro de la aplicación donde tiene el modelo que tiene FileField y desea aceptar un determinado tipo de archivo.

Este es tu formatoChecker.py:

 from django.db.models import FileField from django.forms import forms from django.template.defaultfilters import filesizeformat from django.utils.translation import ugettext_lazy as _ class ContentTypeRestrictedFileField(FileField): """ Same as FileField, but you can specify: * content_types - list containing allowed content_types. Example: ['application/pdf', 'image/jpeg'] * max_upload_size - a number indicating the maximum file size allowed for upload. 2.5MB - 2621440 5MB - 5242880 10MB - 10485760 20MB - 20971520 50MB - 5242880 100MB 104857600 250MB - 214958080 500MB - 429916160 """ def __init__(self, *args, **kwargs): self.content_types = kwargs.pop("content_types") self.max_upload_size = kwargs.pop("max_upload_size") super(ContentTypeRestrictedFileField, self).__init__(*args, **kwargs) def clean(self, *args, **kwargs): data = super(ContentTypeRestrictedFileField, self).clean(*args, **kwargs) file = data.file try: content_type = file.content_type if content_type in self.content_types: if file._size > self.max_upload_size: raise forms.ValidationError(_('Please keep filesize under %s. Current filesize %s') % (filesizeformat(self.max_upload_size), filesizeformat(file._size))) else: raise forms.ValidationError(_('Filetype not supported.')) except AttributeError: pass return data 

Segundo. En su models.py, agregue esto:

 from formatChecker import ContentTypeRestrictedFileField 

Luego, en lugar de usar ‘FileField’, usa este ‘ContentTypeRestrictedFileField’.

Ejemplo:

 class Stuff(models.Model): title = models.CharField(max_length=245) handout = ContentTypeRestrictedFileField(upload_to='uploads/', content_types=['video/x-msvideo', 'application/pdf', 'video/mp4', 'audio/mpeg', ],max_upload_size=5242880,blank=True, null=True) 

Puede cambiar el valor de ‘max_upload_size’ al límite del tamaño de archivo que desee. También puede cambiar los valores dentro de la lista de ‘content_types’ a los tipos de archivo que desea aceptar.

otra solución es usar validadores

 from django.core.exceptions import ValidationError def file_size(value): # add this to some file where you can import it from limit = 2 * 1024 * 1024 if value.size > limit: raise ValidationError('File too large. Size should not exceed 2 MiB.') 

luego en tu forma con el campo Archivo tienes algo como esto

 image = forms.FileField(required=False, validators=[file_size]) 

Creo que el formulario django solo recibe el archivo una vez que se cargó por completo. Por eso, si alguien carga un archivo de 2 Gb, es mucho mejor que el servidor web compruebe el tamaño sobre la marcha.

Vea este hilo de correo para más información.

Solo una breve nota sobre el fragmento que se incluyó en este hilo:

Eche un vistazo a este fragmento: http://www.djangosnippets.org/snippets/1303/

Fue muy útil, sin embargo, incluye algunos pequeños errores. Un código más robusto debería verse así:

 # Add to your settings file CONTENT_TYPES = ['image', 'video'] # 2.5MB - 2621440 # 5MB - 5242880 # 10MB - 10485760 # 20MB - 20971520 # 50MB - 5242880 # 100MB - 104857600 # 250MB - 214958080 # 500MB - 429916160 MAX_UPLOAD_SIZE = "5242880" #Add to a form containing a FileField and change the field names accordingly. from django.template.defaultfilters import filesizeformat from django.utils.translation import ugettext_lazy as _ from django.conf import settings def clean_content(self): if content != None: content = self.cleaned_data['content'] content_type = content.content_type.split('/')[0] if content_type in settings.CONTENT_TYPES: if content._size > int(settings.MAX_UPLOAD_SIZE): raise forms.ValidationError(_(u'Please keep filesize under %s. Current filesize %s') % (filesizeformat(settings.MAX_UPLOAD_SIZE), filesizeformat(content._size))) else: raise forms.ValidationError(_(u'File type is not supported')) return content 

Hay solo algunas mejoras:

En primer lugar, estoy detectando si el campo del archivo está vacío (Ninguno); sin él, Django lanzará una excepción en el navegador web.

A continuación se muestra el tipo de conversión en int (settings.MAX_UPLOAD_SIZE), porque ese valor de configuración es una cadena. Las cadenas no se pueden usar para comparar con números.

Por último, pero no menos importante, el prefijo Unicode ‘u’ en la función ValidationError.

¡Muchas gracias por este fragmento!

Si alguien está buscando una variante FileField forma de @angelo solución, entonces aquí está

 from django import forms from django.template.defaultfilters import filesizeformat from django.utils.translation import ugettext_lazy as _ from django.core.exceptions import ValidationError class RestrictedFileField(forms.FileField): """ Same as FileField, but you can specify: * content_types - list containing allowed content_types. Example: ['application/pdf', 'image/jpeg'] * max_upload_size - a number indicating the maximum file size allowed for upload. 2.5MB - 2621440 5MB - 5242880 10MB - 10485760 20MB - 20971520 50MB - 5242880 100MB - 104857600 250MB - 214958080 500MB - 429916160 """ def __init__(self, *args, **kwargs): self.content_types = kwargs.pop("content_types") self.max_upload_size = kwargs.pop("max_upload_size") super(RestrictedFileField, self).__init__(*args, **kwargs) def clean(self, data, initial=None): file = super(RestrictedFileField, self).clean(data, initial) try: content_type = file.content_type if content_type in self.content_types: if file._size > self.max_upload_size: raise ValidationError(_('Please keep filesize under %s. Current filesize %s') % ( filesizeformat(self.max_upload_size), filesizeformat(file._size))) else: raise ValidationError(_('Filetype not supported.')) except AttributeError: pass return data 

Luego crea un formulario como

 class ImageUploadForm(forms.Form): """Image upload form.""" db_image = RestrictedFileField(content_types=['image/png', 'image/jpeg'], max_upload_size=5242880) 

Lado del servidor

Mi método favorito para verificar si un archivo es demasiado grande en el lado del servidor es la respuesta de ifedapo olarewaju usando un validador.

Lado del cliente

El problema con solo tener una validación del lado del servidor es que la validación solo ocurre después de que se completa la carga. Imagine, cargando un archivo enorme, esperando durante años, solo para que luego se sepa que el archivo es demasiado grande. ¿No sería mejor si el navegador pudiera avisarme de antemano que el archivo es demasiado grande?

¡Bien, hay una forma de llegar a este lado del cliente , usando HTML5 File API !

Aquí está el Javascript requerido (dependiendo de JQuery):

 $("form").submit(function() { if (window.File && window.FileReader && window.FileList && window.Blob) { var file = $('#id_file')[0].files[0]; if (file && file.size > 2 * 1024 * 1024) { alert("File " + file.name + " of type " + file.type + " is too big"); return false; } } }); 

Por supuesto, todavía necesita la validación del lado del servidor, para proteger contra la entrada maliciosa, y los usuarios que no tienen Javascript habilitado.

 from django.forms.utils import ErrorList class Mymodelform(forms.ModelForm): class Meta: model = Mymodel fields = '__all__' def clean(self):image = self.cleaned_data.get('image') # 5MB - 5242880 if org_image._size > 5242880: self._errors["image"] = ErrorList([u"Image too heavy."])