Skillversitas

Uploading Files

File uploads arrive as multipart/form-data: the client streams a binary payload with a filename. FastAPI reads uploads with the UploadFile parameter (which wraps the spooled file, giving you .filename, .content_type, and async read methods) and File parameters for plain form fields sent alongside.

Basic Upload

from fastapi import FastAPI, File, UploadFile

app = FastAPI()

@app.post("/upload/")
async def upload(file: UploadFile):
    content = await file.read()
    return {
        "filename": file.filename,
        "content_type": file.content_type,
        "size": len(content),
    }

Upload it:

curl -X POST http://127.0.0.1:8000/upload/ \
  -F "[email protected]"

Saving to Disk

Read in chunks so large files do not consume all memory, and write to a safe path (sanitize the filename):

import os
from pathlib import Path

UPLOAD_DIR = Path("uploads")
UPLOAD_DIR.mkdir(exist_ok=True)

@app.post("/upload/")
async def upload(file: UploadFile):
    dest = UPLOAD_DIR / (file.filename or "upload.bin")
    with open(dest, "wb") as f:
        while chunk := await file.read(1024 * 1024):
            f.write(chunk)
    return {"saved": str(dest)}

Multiple Files

@app.post("/upload-many/")
async def upload_many(files: list[UploadFile]):
    return [
        {"filename": f.filename, "size": len(await f.read())}
        for f in files
    ]

Files with Form Fields

from fastapi import File, Form, UploadFile

@app.post("/profile/")
async def profile(avatar: UploadFile, nickname: str = Form()):
    content = await avatar.read()
    return {"nickname": nickname, "avatar_bytes": len(content)}

Summary

Declare UploadFile parameters to receive multipart file uploads, read them in chunks with await file.read(), sanitize filenames before writing to disk, and use list[UploadFile] for multiple files. Plain form fields travel alongside files via File()/Form() parameters.