File
and UploadFile
In FastAPI, there are two main ways to handle file uploads: using the File
type and the UploadFile
type.
File
: It is used to receive file data as bytes. This is suitable for small files where you want to handle the data directly as a byte string.UploadFile
: It is a more advanced way to handle file uploads. It represents an uploaded file and provides useful attributes and methods such as filename
, content_type
, and file
(a file-like object that can be used to read the file’s contents). It is recommended for handling larger files as it reads the file in chunks, which is more memory-efficient.File uploads in web applications typically use the multipart/form-data
encoding type. When a client sends a file to the server, the data is divided into multiple parts, each with its own headers and content. FastAPI can automatically parse this multipart/form-data
and extract the file data for you.
File
The following is a simple example of using the File
type to handle a file upload:
from fastapi import FastAPI, File
app = FastAPI()
@app.post("/upload-file/")
async def upload_file(file: bytes = File()):
# Here we just return the length of the file data
return {"file_size": len(file)}
In this example, the file
parameter is of type bytes
, and FastAPI will automatically read the entire file contents into memory as a byte string.
UploadFile
The following is an example of using the UploadFile
type:
from fastapi import FastAPI, UploadFile
app = FastAPI()
@app.post("/upload-file-uploadfile/")
async def upload_file_uploadfile(file: UploadFile = File()):
contents = await file.read()
# Here we just return the length of the file data
return {"filename": file.filename, "file_size": len(contents)}
In this example, the file
parameter is of type UploadFile
. We can access the file’s filename using file.filename
and read the file’s contents using await file.read()
.
FastAPI allows you to handle multiple file uploads by using a list of File
or UploadFile
types. Here is an example of handling multiple file uploads using UploadFile
:
from fastapi import FastAPI, UploadFile
app = FastAPI()
@app.post("/upload-multiple-files/")
async def upload_multiple_files(files: list[UploadFile] = File()):
results = []
for file in files:
contents = await file.read()
results.append({"filename": file.filename, "file_size": len(contents)})
return results
Often, you’ll want to save the uploaded files to disk. Here is an example of saving an uploaded file using UploadFile
:
import os
from fastapi import FastAPI, UploadFile
app = FastAPI()
UPLOAD_DIR = "uploads"
if not os.path.exists(UPLOAD_DIR):
os.makedirs(UPLOAD_DIR)
@app.post("/save-file/")
async def save_file(file: UploadFile = File()):
file_path = os.path.join(UPLOAD_DIR, file.filename)
with open(file_path, "wb") as f:
contents = await file.read()
f.write(contents)
return {"message": f"File {file.filename} saved successfully"}
To prevent users from uploading extremely large files, you can add file size limitations. Here is an example of adding a file size limitation using a custom middleware:
from fastapi import FastAPI, File, UploadFile, Request, HTTPException
app = FastAPI()
MAX_FILE_SIZE = 1024 * 1024 # 1MB
@app.middleware("http")
async def check_file_size(request: Request, call_next):
content_length = request.headers.get("content-length")
if content_length and int(content_length) > MAX_FILE_SIZE:
raise HTTPException(status_code=413, detail="File size exceeds the limit")
response = await call_next(request)
return response
@app.post("/upload-limited-file/")
async def upload_limited_file(file: UploadFile = File()):
contents = await file.read()
return {"filename": file.filename, "file_size": len(contents)}
You can also validate the file type to ensure that only certain types of files are allowed to be uploaded. Here is an example of validating the file type based on the file’s content type:
from fastapi import FastAPI, UploadFile, HTTPException
app = FastAPI()
ALLOWED_FILE_TYPES = ["image/jpeg", "image/png"]
@app.post("/upload-validated-file/")
async def upload_validated_file(file: UploadFile = File()):
if file.content_type not in ALLOWED_FILE_TYPES:
raise HTTPException(status_code=400, detail="Invalid file type")
contents = await file.read()
return {"filename": file.filename, "file_size": len(contents)}
Handling file uploads in FastAPI is relatively straightforward. By using the File
and UploadFile
types, you can easily receive and process file data. However, when dealing with file uploads, it’s important to consider factors such as file size limitation and file type validation to ensure the security and stability of your application. With the knowledge and examples provided in this blog post, you should be able to handle file uploads efficiently in your FastAPI applications.