Django File Upload Image Validate Fix
In this tutorial, you'll learn about Django File Upload Image Validate Fix. We cover key concepts, practical examples, and best practices.
The Problem
Users upload non-image files to ImageField, or upload huge images that crash the server. Without validation, you get corrupted data, disk overflow, or HTML files posing as images (XSS risk).
Quick Fix
Wrong — no validation on ImageField
class Profile(models.Model):
avatar = models.ImageField(upload_to='avatars/')
Output: Any file can be uploaded as avatar. 100MB photos crash the server. JavaScript files can be renamed as .png and uploaded.
Correct — custom image validator
from django.core.exceptions import ValidationError
from django.core.validators import FileExtensionValidator
from PIL import Image
import os
def validate_image(image):
max_size_mb = 5
max_width = 2048
max_height = 2048
if image.size > max_size_mb * 1024 * 1024:
raise ValidationError(f"Max file size is {max_size_mb}MB")
try:
img = Image.open(image)
width, height = img.size
if width > max_width or height > max_height:
raise ValidationError(f"Max dimensions: {max_width}x{max_height}px")
img.verify() # Verify it's a valid image
except Exception:
raise ValidationError("Invalid image file")
class Profile(models.Model):
avatar = models.ImageField(
upload_to='avatars/',
validators=[validate_image, FileExtensionValidator(['jpg', 'jpeg', 'png', 'webp'])],
help_text="Max 5MB, max 2048x2048px"
)
Rejecting by content type (not just extension)
import magic
def validate_image_content(image):
mime = magic.from_buffer(image.read(1024), mime=True)
image.seek(0)
allowed = ['image/jpeg', 'image/png', 'image/webp']
if mime not in allowed:
raise ValidationError(f"Invalid image type: {mime}")
Serializer-level validation (DRF)
from rest_framework import serializers
class AvatarSerializer(serializers.Serializer):
avatar = serializers.ImageField()
def validate_avatar(self, value):
if value.size > 5 * 1024 * 1024:
raise serializers.ValidationError("Max 5MB")
if value.content_type not in ['image/jpeg', 'image/png']:
raise serializers.ValidationError("JPEG or PNG only")
return value
Thumbnail generation on upload
from django.db.models.signals import post_save
from PIL import Image
@receiver(post_save, sender=Profile)
def create_thumbnail(sender, instance, **kwargs):
if instance.avatar and not instance.thumbnail:
img = Image.open(instance.avatar.path)
img.thumbnail((200, 200))
thumb_path = instance.avatar.path.replace('avatars/', 'thumbs/')
os.makedirs(os.path.dirname(thumb_path), exist_ok=True)
img.save(thumb_path)
Prevention
- Always validate file size, dimensions, and content type on ImageField.
- Use
FileExtensionValidatorplus content-type sniffing. - Resize large images on upload to prevent storage waste.
Common Mistakes with file upload image validate
- Misunderstanding that
Stringis[Char]with poor performance for large text operations - Using
foldlinstead offoldl'causing stack overflow on large lists - Forgetting
deriving (Show, Eq)on custom data types needed for debugging
These mistakes appear frequently in real-world DJANGO code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro