JSON 之外: 表单数据与文件上传
超越 JSON:表单数据和文件上传
Section titled “超越 JSON:表单数据和文件上传”虽然 JSON 是现代 API 的标准,但有时您需要与传统的 HTML 表单交互或处理文件上传。FastAPI 能够优雅地处理这些非 JSON 请求,但这需要一种特定的方法。
设置:安装 python-multipart
Section titled “设置:安装 python-multipart”为了处理上传文件和表单数据,FastAPI 依赖于一个名为 python-multipart 的外部库。在继续之前,您必须安装它:
pip install python-multipart处理表单数据
Section titled “处理表单数据”当从 HTML <form> 接收数据时,媒体类型通常是 application/x-www-form-urlencoded。这与 JSON 不同。要告诉 FastAPI 从表单数据而不是 JSON 中读取,请使用 Form 类。
from typing import Annotatedfrom fastapi import FastAPI, Form
app = FastAPI()
@app.post("/login/")async def login(username: Annotated[str, Form()], password: Annotated[str, Form()]): return {"username": username}这与 Body、Query 或 Path 的工作方式完全相同。它告诉 FastAPI 在表单数据中查找 username 和 password 字段。
文件上传:bytes vs UploadFile
Section titled “文件上传:bytes vs UploadFile”FastAPI 提供了两种定义文件参数的方式:bytes (使用 File) 和 UploadFile。
1. 将文件作为 bytes
Section titled “1. 将文件作为 bytes”如果您将类型声明为 bytes,FastAPI 将把整个文件读入内存。
from fastapi import File
@app.post("/files/")async def create_file(file: Annotated[bytes, File()]): return {"file_size": len(file)}这对于小文件来说很简单,但对于大文件(如视频)来说,它可能会耗尽您服务器的所有内存并导致应用程序崩溃。
2. UploadFile (推荐)
Section titled “2. UploadFile (推荐)”使用 UploadFile 更安全、功能更丰富。它使用了 Python 的 SpooledTemporaryFile。这意味着它会在内存中保留到达到一定大小限制,然后自动溢出到磁盘。
from fastapi import UploadFile
@app.post("/uploadfile/")async def create_upload_file(file: UploadFile): return {"filename": file.filename, "content_type": file.content_type}两种方法的比较:
| 特性 | bytes | UploadFile |
|---|---|---|
| 存储 | 完全存储在 RAM 中 | 缓冲池(RAM + 磁盘) |
| 性能 | 对小文件快速 | 对大文件高效 |
| 元数据 | 无(仅原始数据) | 包含文件名、内容类型 |
| 接口 | Python bytes 对象 | 类文件对象(读/写/关闭) |
通过声明一个 UploadFile 列表,您可以一次处理多个文件。
from typing import List
@app.post("/uploadfiles/")async def create_upload_files(files: List[UploadFile]): return {"filenames": [file.filename for file in files]}此端点将接受发送多个文件(例如 <input type="file" multiple>)的 HTML 表单并高效地处理它们。