小菜鸟学AI:Form表单,文件上传与Cookie指南
一、Form 表单:不只 JSON 一种选择
在 FastAPI 中,Form 专门用来处理传统 HTML 表单提交的数据
from fastapi import FastAPI, Form
app = FastAPI()
@app.post("/login/")
async def login(username: str = Form(...), password: str = Form(...)):
return {"username": username}
必知要点:
- 必须显式使用 Form(...),否则 FastAPI 会将参数当成查询参数或 JSON 请求体参数
- 必须先安装 python-multipart:pip install python-multipart
- 一个路径操作中可以声明多个 Form 参数,但不能同时声明要接收 JSON 的 Body 字段,这是 HTTP 协议的限制
表单模型(进阶封装)
当表单字段很多时(比如注册场景),可以用 Pydantic 模型进行结构化封装:
from pydantic import BaseModel
class RegisterForm(BaseModel):
username: str = Form(...)
email: str = Form(...)
password: str = Form(...)
confirm_password: str = Form(...)
@app.post("/register")
async def register_user(form: Annotated[RegisterForm, Form()]):
if form.password != form.confirm_password:
return {"error": "Passwords do not match"}
return {"message": f"User {form.username} registered successfully"}
二、文件上传:UploadFile vs bytes
FastAPI 提供了两种接收文件的方式,选择哪种直接决定了性能和安全性。
2.1 bytes:小文件可用,但有风险
把文件全部读入内存,只适合几 KB 的头像或配置文件。大文件会导致内存暴涨。
2.2 UploadFile:生产环境标配
这是更推荐的异步方式。文件会分块处理,大文件自动写入磁盘临时文件,不会撑爆内存。
单文件上传示例:
from fastapi import FastAPI, File, UploadFile
import aiofiles
@app.post("/upload/")
async def upload_file(file: UploadFile = File(...)):
# 异步保存到本地
async with aiofiles.open(f"uploads/{file.filename}", "wb") as out_file:
content = await file.read()
await out_file.write(content)
return {"filename": file.filename, "message": "上传成功"}
UploadFile 核心属性与方法:
· 属性:file.filename(文件名)、file.content_type(如 image/jpeg)、file.file(类文件对象)
· 异步方法:await file.read(size)、await file.write(data)、await file.seek(offset)、await file.close()
多文件上传:
from typing import List
@app.post("/upload-multiple/")
async def upload_multiple(files: List[UploadFile] = File(...)):
for file in files:
# 处理每个文件
contents = await file.read()
print(f"Received {file.filename}, size: {len(contents)}")
return {"file_count": len(files)}
2.3 同时接收文件与表单数据
这是常见需求——比如上传图片的同时提交用户ID。FastAPI 中同时使用 File 和 Form 即可:
@app.post("/files/")
async def create_file(
file: UploadFile = File(...),
token: str = Form(...)
):
return {
"file_name": file.filename,
"token": token,
"file_content_type": file.content_type
}
三、Cookie:客户端的“会员卡”
Cookie 是服务器存储在浏览器的小段数据,每次请求浏览器都会自动带上它。常见用途是会话管理、用户偏好设置等。
3.1 读取 Cookie
FastAPI 用 Cookie() 函数直接注入指定 cookie 值:
from fastapi import Cookie
@app.get("/items/")
async def read_items(ads_id: str | None = Cookie(default=None)):
return {"ads_id": ads_id}
Cookie 也可以用 Pydantic 模型进行结构化校验(FastAPI 0.115.0+):
from pydantic import BaseModel
class Cookies(BaseModel):
session_id: str
fatebook_tracker: str | None = None
@app.get("/items/")
async def read_items(cookies: Annotated[Cookies, Cookie()]):
return cookies
3.2 设置 Cookie
设置 Cookie 必须通过 Response 对象,直接在返回的字典里设置是无效的。
登录后设置 Cookie 的完整示例:
from fastapi.responses import JSONResponse
@app.post("/login/")
async def login(username: str = Form(...), password: str = Form(...)):
# 验证密码逻辑略...
response = JSONResponse(content={"message": "登录成功"})
response.set_cookie(
key="session_id",
value="abc123xyz",
max_age=3600, # 有效期1小时(秒)
httponly=True, # 禁止JS读取,防XSS攻击
secure=True, # 仅HTTPS传输
samesite="lax" # CSRF保护
)
return response
set_cookie 关键参数说明:
| 参数 | 作用 |
| key | Cookie名称 |
| value | Cookie值 |
| max_age | 有效期(秒) |
| expires | 到期日期(datetime) |
| path | 生效路径 |
| domain | 生效域名 |
| secure | 设为True时仅HTTP发送 |
| httponly | 设为True时禁止JavaScript访问 |
| samesite | CSRF防护:lax,strict或none |
四、常见陷阱与最佳实践
- 避免 JSON 与 Form 混用:一个接口不能同时要求 JSON 请求体和表单数据,FastAPI 按 Content-Type 决定解析方式,这不是框架限制,是 HTTP 协议本身的规定。
- 异步别忘了 await:UploadFile 的 read()、write() 等方法都是异步的,漏写 await 不会报语法错,但会导致文件内容读取为协程对象而非实际数据。
- Cookie 在 Swagger 文档中无法调试:Swagger UI 依赖 JS 发送请求,浏览器出于安全限制不允许 JS 随意操作 Cookie,所以在 /docs 里测试 Cookie 接口会报错,可以用 Postman 或 curl 测试。
- 文件上传记得保存:很多新手只调了 file.read() 读取内容,却没有写入磁盘。请求结束后内存数据就没了,必须用 shutil.copyfileobj 或 aiofiles 写到指定路径。
- 路径尾部斜杠问题:FastAPI 的路径匹配默认有“尾部斜杠重定向”机制,建议在路由定义时就统一加 / 或不加,避免意外重定向导致 Form 数据丢失。
学习 FastAPI 处理 Form、文件上传与 Cookie 后,最大的体会是:别用处理 JSON 的思路套在所有场景上。表单必须用 Form() 声明并安装 python-multipart;大文件首选 UploadFile 异步分块,避免内存溢出;设置 Cookie 必须通过响应对象操作,留意 httponly 和 secure 等安全属性。理解 HTTP 协议层面的差异,比学会框架 API 更重要。
下期预告:MySQL
作者:不爱编程的同学127 日期:2026.4.28
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)