Form Data & File Uploads¶
HTML forms and file uploads use multipart/form-data or
application/x-www-form-urlencoded — not JSON. FasterAPI handles both with the
Form(), File(), and UploadFile helpers.
Form fields¶
from FasterAPI import Faster, Form
app = Faster()
@app.post("/login")
async def login(username: str = Form(), password: str = Form()):
return {"username": username}
Note
You cannot mix Form() fields and a JSON body (msgspec.Struct) in the same
endpoint — HTTP only allows one body encoding per request.
Uploading a single file¶
from FasterAPI import Faster, UploadFile, File
app = Faster()
@app.post("/upload")
async def upload_file(file: UploadFile = File()):
contents = await file.read()
return {"filename": file.filename, "size": len(contents)}
UploadFile exposes:
| Attribute / method | Description |
|---|---|
filename |
Original filename from the client |
content_type |
MIME type (e.g. image/png) |
await file.read() |
Read all bytes |
await file.read(n) |
Read up to n bytes |
Multiple files¶
@app.post("/multi-upload")
async def multi_upload(files: list[UploadFile] = File()):
return [{"filename": f.filename} for f in files]
Mixed form and file¶
Combine Form() and File() fields freely:
@app.post("/profile")
async def update_profile(
bio: str = Form(),
avatar: UploadFile = File(),
):
data = await avatar.read()
return {"bio": bio, "avatar_size": len(data)}
Form with optional file¶
@app.post("/create-post")
async def create_post(
title: str = Form(),
image: UploadFile | None = File(default=None),
):
return {"title": title, "has_image": image is not None}
Accessing raw form data¶
from FasterAPI import Request
@app.post("/raw-form")
async def raw_form(request: Request):
form = await request.form()
return dict(form)
Next steps¶
- Error Handling — what happens when validation fails.
- Dependencies — reuse form parsing across routes.