inmemoryuploadedfile - upload image django example
Límite de tamaño de carga del archivo Django (8)
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?
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.
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.
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.
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)
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!
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])
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."])