File Uploads in FastAPI with UploadFile addresses a recurring problem in Python projects: Accept uploads without trusting client-provided names, extensions, or media types. This guide explains the mechanism, provides an executable example, and identifies the boundaries that keep an implementation reliable.
Concept and use case
UploadFile uses a spooled temporary file and exposes an async interface, making it preferable to bytes when files may grow. Browser uploads use multipart/form-data.
For the related fundamentals, also read the FastAPI API guide. Integration stays simpler when functions receive dependencies and data explicitly instead of relying on global state.
Practical example
from typing import Annotated
from fastapi import FastAPI, File, HTTPException, UploadFile
app = FastAPI()
@app.post("/files")
async def upload(file: UploadFile):
if file.content_type not in {"image/png", "image/jpeg"}:
raise HTTPException(415, "Unsupported media type")
data = await file.read(2_000_001)
if len(data) > 2_000_000:
raise HTTPException(413, "File too large")
return {"name": file.filename, "size": len(data)}
Read with a limit, generate an internal name, and store outside executable directories. content_type is only a hint; inspect the actual signature when format matters.
Important decisions
The correct choice depends on the public contract, expected volume, and failure behavior.
Consider concurrency, empty inputs, and partial failures. Document every limit that affects consumers and choose names that express intent.
Common mistakes
A minimal example does not replace bounds, error handling, and observability. Never turn the original filename into a path, accept an extension as proof, or read an unlimited body into memory. Add malware scanning when the threat model requires it.
Avoid catching exceptions without context or returning partial output as if it were complete. An explicit failure is usually safer than silently incorrect data.
How to validate
Validate behavior, not only the happy path. Test a valid file, empty input, oversized data, a traversal filename, and content that disagrees with the declared type. Verify temporary-file cleanup.