In web applications, form data is used to collect information from users through HTML forms. In FastAPI, form data is typically sent using the application/x-www-form-urlencoded
or multipart/form-data
media types. The Form
class in FastAPI is used to handle form data.
File uploads are a common requirement in web applications, such as allowing users to upload profile pictures, documents, etc. FastAPI uses the File
class to handle file uploads. When a user uploads a file, the file data is sent as part of a multipart/form-data
request.
from fastapi import FastAPI, Form
app = FastAPI()
@app.post("/login/")
async def login(username: str = Form(...), password: str = Form(...)):
return {"username": username, "password": password}
In this example, we define a simple login endpoint that expects two form fields: username
and password
. The Form(...)
indicates that these fields are required.
Form
in Pydantic Modelsfrom fastapi import FastAPI, Form
from pydantic import BaseModel
app = FastAPI()
class LoginData(BaseModel):
username: str
password: str
@app.post("/login-model/")
async def login_model(username: str = Form(...), password: str = Form(...)):
login_data = LoginData(username=username, password=password)
return login_data
Here, we use a Pydantic model to structure the form data. This can be useful for more complex data validation and serialization.
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
contents = await file.read()
return {"filename": file.filename, "file_size": len(contents)}
In this example, we use the UploadFile
class to handle a single file upload. The File(...)
indicates that the file is required.
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/uploadfiles/")
async def create_upload_files(files: list[UploadFile] = File(...)):
file_sizes = []
for file in files:
contents = await file.read()
file_sizes.append(len(contents))
return {"filenames": [file.filename for file in files], "file_sizes": file_sizes}
This code allows users to upload multiple files at once. The files
parameter is a list of UploadFile
objects.
from fastapi import FastAPI, Form
from pydantic import BaseModel, Field
app = FastAPI()
class UserRegistration(BaseModel):
username: str = Field(min_length=3, max_length=20)
email: str = Field(regex=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")
@app.post("/register/")
async def register(username: str = Form(...), email: str = Form(...)):
user_data = UserRegistration(username=username, email=email)
return user_data
We use Pydantic’s Field
to add validation rules to the form data. This ensures that the input data meets certain criteria.
from fastapi import FastAPI, Form, HTTPException
app = FastAPI()
@app.post("/login-error/")
async def login_error(username: str = Form(...), password: str = Form(...)):
if not username or not password:
raise HTTPException(status_code=400, detail="Username and password are required")
return {"username": username, "password": password}
In this example, we raise an HTTPException
if the form data is incomplete.
from fastapi import FastAPI, File, UploadFile, HTTPException
app = FastAPI()
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg'}
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.post("/upload-image/")
async def upload_image(file: UploadFile = File(...)):
if not allowed_file(file.filename):
raise HTTPException(status_code=400, detail="Invalid file type. Allowed types: png, jpg, jpeg")
return {"filename": file.filename}
For large file uploads, it’s recommended to process the files asynchronously to avoid blocking the event loop. FastAPI’s UploadFile
class already provides asynchronous methods like read()
which can be used to read the file content asynchronously.
import asyncio
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/upload-large-file/")
async def upload_large_file(file: UploadFile = File(...)):
async def process_file():
contents = await file.read()
# Do some long - running processing here
await asyncio.sleep(5)
return len(contents)
file_size = await process_file()
return {"filename": file.filename, "file_size": file_size}
FastAPI provides a powerful and easy - to - use set of tools for handling form data and file uploads. By understanding the fundamental concepts, usage methods, common practices, and best practices, developers can build robust and secure web applications that handle user input effectively. Whether it’s a simple login form or a complex file upload feature, FastAPI has got you covered.