Skip to content

Instantly share code, notes, and snippets.

@gregplaysguitar
Created June 27, 2012 00:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gregplaysguitar/3000513 to your computer and use it in GitHub Desktop.
Save gregplaysguitar/3000513 to your computer and use it in GitHub Desktop.
Memory-safe ImageField for Django - checks filesize and dimensions before loading the uploaded file into memory.
try:
from PIL import Image
except ImportError:
import Image
from django import forms
from django.template.defaultfilters import filesizeformat
from django.core.exceptions import ValidationError
class MemorySafeImageField(forms.ImageField):
"""Image field that checks the size and dimensions of the image in its
metadata *before* trying to load the damn thing into memory.
Pixel dimensions are important because images are loaded into memory
as a bitmap, so MB can easily become GB when working with compressed
image formats.
Requires `max_dimensions` and `max_size` keyword arguments."""
def __init__(self, *args, **kwargs):
self.max_dimensions = kwargs.pop('max_dimensions')
self.max_size = kwargs.pop('max_size')
super(MemorySafeImageField, self).__init__(self, *args, **kwargs)
def to_python(self, data):
# this isn't a mistake - the ImageField.to_python method is what causes the problem
f = super(forms.ImageField, self).to_python(data)
if f is None:
return None
if f.size > self.max_size:
raise ValidationError('Maximum filesize is %s. This file is %s' % (filesizeformat(self.max_size), filesizeformat(data.size)))
try:
dimensions = Image.open(f).size
except IOError:
raise forms.ValidationError(u'That doesn\'t appear to be an image')
else:
if dimensions[0] > self.max_dimensions[0] or dimensions[1] > self.max_dimensions[1]:
raise forms.ValidationError(u'Maximum image dimensions are %sx%s px. This file is %sx%s px' % (self.max_dimensions + dimensions))
f.seek(0)
return super(MemorySafeImageField, self).to_python(data)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment