FastAPI File Upload
FastAPI providesFileandUploadFileTwo ways to handle file uploads, supporting standalone file uploads and mixed form-and-file uploads.
Install dependencies
File upload also depends onpython-multipart:
pip install python-multipart
Using UploadFile
UploadFileis the recommended approach, it provides a richer interface for accessing file information:
Example
app = FastAPI()
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
# Properties and methods provided by UploadFile
return {
"filename": file.filename, # File name
"content_type": file.content_type, # File MIME type
"size": file.size, # File size (bytes)
}
UploadFileproperties and methods:
| Attributes/Methods | Type | Description |
|---|---|---|
filename | str | None | The original filename of the uploaded file |
content_type | str | None | The MIME type of the file (e.g.image/png) |
file | SpooledTemporaryFile | A file-like object that can read file contents |
size | int | None | File size (bytes) |
read() | Methods | Read file content asbytes |
write() | Methods | Write content to file |
seek() | Methods | Move file pointer position |
close() | Methods | Close a File |
UploadFileUses "SpooledTemporaryFile" to store file contents. When the file is small, it is kept in memory; when the file is large, it is automatically written to disk, so it is morebytesMore memory-efficient.
Use File to receive file content
FileDirectly read the file content asbytes, suitable for small files:
Example
app = FastAPI()
@app.post("/files/")
async def create_file(file: bytes = File()):
# file is the raw byte data of the file
return {"file_size": len(file)}
FileandUploadFilecomparison:
| Comparison Item | File | UploadFile |
|---|---|---|
| Data types | bytes | File object |
| Memory usage | Load the entire file into memory | Large files are automatically written to disk |
| File information | None (only content) | Has filename, type, size |
| Applicable scenarios | small file | Scenarios with large files or needing file information |
Optional file upload
Use default valueNoneMake file upload optional:
Example
app = FastAPI()
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile | None = None):
if not file:
return {"message": "No file uploaded"}
return {"filename": file.filename}
Multi-file upload
Use a list to receive multiple files:
Example
app = FastAPI()
@app.post("/uploadfiles/")
async def create_upload_files(files: list[UploadFile]):
return {"filenames": [file.filename for file in files]}
Mixed form and file upload
You can receive form data and files simultaneously in the same route:
Example
app = FastAPI()
@app.post("/items/")
async def create_item(
# Form Fields
name: str = Form(...),
description: str | None = Form(None),
# File Upload
file: UploadFile | None = None,
):
result = {"name": name, "description": description}
if file:
result["filename"] = file.filename
return result
Save uploaded file
The following example shows how to save uploaded files to disk:
Example
from fastapi import FastAPI, UploadFile
app = FastAPI()
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
# Save the uploaded file to the specified path
with open(f"uploads/{file.filename}", "wb") as buffer:
shutil.copyfileobj(file.file, buffer)
return {"filename": file.filename, "message": "File uploaded successfully"}
In actual projects, when uploading files, note: 1) Validate file type and size; 2) Use safe filenames (avoid path traversal attacks); 3) Restrict permissions on the upload directory; 4) For large files, use streaming instead of reading all at once.
Summary
- Recommended
UploadFile, it saves more memory and provides rich file information FileSuitable for small file scenarios, directly read asbytes- Usage
list[UploadFile]Receive multiple file uploads - form (
Form) and file (UploadFile) can be used in the same route - Pay attention to security when uploading files: validate file types, use safe filenames, and limit sizes