한양과학기술고등학교

에듀테크 프로젝트 대시보드

폼 데이터와 파일 업로드

Form UploadFile python-multipart StaticFiles

JSON 이 아닌 multipart/form-data 요청 — HTML 폼 전송과 파일 업로드를 다룹니다.

1. 사전 준비

pip install python-multipart

폼·파일 파싱에 필요합니다. fastapi[standard] 에는 포함되어 있습니다.

2. 폼 필드

from typing import Annotated
from fastapi import Form

@app.post("/login")
def login(
    username: Annotated[str, Form()],
    password: Annotated[str, Form()],
):
    ...
# Content-Type: application/x-www-form-urlencoded 또는 multipart/form-data

3. 파일 업로드

from fastapi import UploadFile
import shutil, pathlib

UPLOAD_DIR = pathlib.Path("uploads")

@app.post("/upload")
async def upload(file: UploadFile):
    dest = UPLOAD_DIR / file.filename
    with dest.open("wb") as buffer:
        shutil.copyfileobj(file.file, buffer)
    return {"filename": file.filename, "size": file.size, "type": file.content_type}
UploadFile 이점
  • 스풀 파일 — 작은 파일은 메모리, 큰 파일은 디스크로 자동 전환
  • await file.read() / await file.write() / await file.seek(0)
  • bytes 로 받으면 전체가 메모리에 올라감 — 큰 파일은 UploadFile

4. 다중 파일 + 폼 필드 혼합

@app.post("/posts")
async def create_post(
    title: Annotated[str, Form()],
    files: list[UploadFile],
):
    return {"title": title, "count": len(files)}

5. 정적 파일 서빙

from fastapi.staticfiles import StaticFiles

app.mount("/static", StaticFiles(directory="static"), name="static")
app.mount("/uploads", StaticFiles(directory="uploads"), name="uploads")

운영에서는 정적 파일을 Nginx 가 직접 서빙하는 편이 빠릅니다 (location /static/).

"느린 것은 async 로, 무거운 것은 백그라운드로"