FastAPI: Use UploadFile for Efficient File Uploads
FastAPI handles file uploads as 'form data', giving you a streamable `UploadFile` object instead of a raw byte blob. Use this for endpoints like image or document submissions. The footgun is reading large files into memory instead of streaming them.
WHY IT EXISTS APIs often need to accept files, not just JSON. HTTP handles this using multipart/form-data encoding, which mixes metadata and file data in a single request. FastAPI needs a way to parse this format and present the file to your code in a memory-efficient way, especially for large uploads that could exhaust server RAM if loaded all at once.
THE MENTAL MODEL Think of a file upload not as a single giant variable, but as a spooled file temporarily stored on disk or in memory up to a certain limit. FastAPI, using the UploadFile class, gives you a pointer to this temporary file. You can read its metadata (like filename) or stream its contents piece by piece, but you don't hold the whole thing in memory unless you explicitly ask to. This prevents a single large upload from crashing your application.
HOW IT WORKS First, you must pip install python-multipart, as it's the library that parses the multipart/form-data encoding. In your path operation function, you define a parameter and type-hint it as UploadFile from fastapi. You then assign it a default value of File() from fastapi. For example: async def create_upload_file(file: UploadFile = File()):. FastAPI then knows to expect a file part in the form data. The file variable in your function will be an UploadFile object, which has useful attributes like file.filename and file.content_type, and async methods like await file.read() to get the contents.
WHEN TO USE IT Use this anytime an API endpoint needs to receive a file from a client. Common cases include: uploading a user's profile picture, submitting a report in PDF or CSV format, or importing a dataset for processing. It's the standard, built-in way to handle files in FastAPI.
WHEN NOT TO USE IT If you are receiving a small, base64-encoded file string inside a JSON payload, you might just decode it from the JSON body directly. However, for actual file uploads via an HTML form or a client library, using UploadFile is almost always the correct and most efficient method. It is designed for this exact purpose.
ONE CANONICAL EXAMPLE To create an endpoint that saves an uploaded file, you would define a function like async def upload(file: UploadFile):. Inside, you can read the contents and save them. For example, to save it locally: with open(file.filename, 'wb') as buffer: content = await file.read(); buffer.write(content);. This reads the entire file into memory before writing, which is okay for small files. For very large files, you should read and write in chunks to avoid high memory usage.
Read the original → fastapi.tiangolo.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.