Python FastAPI Tutorial (Part 12): File Uploads - Image Processing, Validation, and Storage
TL;DR
Corey Schafer demonstrates implementing secure profile picture uploads in FastAPI using Pillow for image resizing and format standardization, with proper handling of CPU-bound tasks in async contexts and safe file transaction patterns to prevent data loss.
🖼️ Image Processing Setup 3 insights
Process images with Pillow
Resize uploads to 300x300 pixels using LANCZOS resampling, convert to RGB format to handle transparency, fix EXIF orientation issues, and save as optimized JPEG with quality set to 85.
Handle CPU-bound work in async contexts
Offload image processing to separate threads using Starlette's run_in_threadpool to prevent blocking the async event loop during computationally intensive Pillow operations.
Generate secure unique filenames
Create UUID4 filenames instead of using client-provided names to prevent file collisions, directory traversal attacks, and security issues from malicious file names.
🔒 Security & Validation 3 insights
Validate actual file content
Verify uploaded files are valid images by attempting to open them with Pillow and catching UnidentifiedImageError rather than trusting client-provided Content-Type headers.
Enforce upload size limits
Configure a maximum file size setting (default 5MB) and validate content length after reading to protect the server from excessive memory consumption and denial-of-service attacks.
Secure API schemas
Remove image_file fields from Pydantic update schemas to prevent users from manipulating file paths directly through JSON endpoints, restricting changes to dedicated upload endpoints only.
⚡ Safe File Operations 3 insights
Maintain safe transaction ordering
Save new image files to disk before updating the database, and only delete old files after successful database commits to prevent losing user profile pictures if transactions fail.
Use dedicated upload endpoints
Create separate PATCH endpoints using UploadFile for multipart/form-data rather than mixing binary file data with JSON payloads, keeping concerns clean and manageable.
Implement proper cleanup
Delete physical profile picture files when users upload replacements or delete their accounts, but only after confirming database updates succeed to avoid orphaned files or broken references.
Bottom Line
Validate file integrity with Pillow instead of trusting client headers, process images in thread pools to avoid blocking async endpoints, and always delete old files after database commits succeed to prevent permanent data loss.
More from Corey Schafer
View all
Python FastAPI Tutorial (Part 19): Deploy with Docker - Serverless Containers and Custom Domain
This tutorial demonstrates how to deploy a FastAPI application to Google Cloud Run using Docker containers, implementing security headers via middleware, leveraging multi-stage builds with the UV package manager for optimization, and configuring the container for serverless deployment with proper signal handling and non-root user privileges.
Python FastAPI Tutorial (Part 18): Deploy to a VPS - Security, Nginx, SSL, and Custom Domain
Corey Schafer demonstrates how to deploy a production-ready FastAPI application to a Virtual Private Server (VPS), emphasizing fundamental deployment concepts including security hardening, SSH key authentication, and health check implementation before moving to managed cloud solutions.
Python FastAPI Tutorial (Part 17): Testing the API - Pytest, Fixtures, and Mocking External Services
This tutorial demonstrates how to implement comprehensive testing for FastAPI applications using pytest with async support, covering critical setup patterns like environment variable configuration before app imports, using AsyncClient for async endpoints, mocking AWS S3 with Moto, and maintaining a separate PostgreSQL test database to ensure production parity.
Python FastAPI Tutorial (Part 16): AWS S3 and Boto3 - Moving File Uploads to the Cloud
This tutorial demonstrates how to migrate a FastAPI application from local disk storage to AWS S3 for production file uploads, covering S3 bucket setup, IAM security configuration, and Boto3 integration while maintaining separation between image processing and storage layers.