FastAPI入门:表单数据、表单模型、请求文件、请求表单与文件
表单数据
接收的不是 JSON,而是表单字段时,要使用 Form。要使用表单,需预先安装 python-multipart。
pip install python-multipart
创建表单(Form)参数的方式与 Body 和 Query 一样
from fastapi import FastAPI, Formapp = FastAPI()@app.post("/login/")
async def login(username: str = Form(), password: str = Form()):return {"username": username}
表单模型
使用pydantic声明一个数据模型,并在请求中声明它为Form()对象
from fastapi import FastAPI, Form
from pydantic import BaseModel
from typing import Annotatedapp = FastAPI()class FormData(BaseModel):username: strpassword: str@app.post("/login")
async def login(data: Annotated[FormData, Form()]):return data
禁止额外的表单字段
使用 Pydantic 的模型配置来禁止( forbid )任何额外( extra )字段
model_config = {"extra": "forbid"}
请求文件
File 用于定义客户端的上传文件
创建文件(File)参数的方式与 Body 和 Form 一样。如果把路径操作函数参数的类型声明为 bytes,FastAPI 将以 bytes 形式读取和接收文件内容。
这种方式把文件的所有内容都存储在内存里,适用于小型文件
from fastapi import FastAPI, File, UploadFileapp = FastAPI()@app.post("/files")
async def create_file(file: bytes = File()):return {"file_size": len(file)}
UploadFile 与 bytes 相比有更多优势:
- 使用 spooled 文件:
- 存储在内存的文件超出最大上限时,FastAPI 会把文件存入磁盘;
- 这种方式更适于处理图像、视频、二进制文件等大型文件,好处是不会占用所有内存;
- 可获取上传文件的元数据;
- 自带 file-like async 接口;
- 暴露的 Python SpooledTemporaryFile 对象,可直接传递给其他预期「file-like」对象的库。
UploadFile 的属性如下:##
- filename:上传文件名字符串(str),例如, myimage.jpg;
- content_type:内容类型(MIME 类型 / 媒体类型)字符串(str),例如,image/jpeg;
- file: SpooledTemporaryFile( file-like 对象)。其实就是 Python文件,可直接传递给其他预期 file-like 对象的函数或支持库。
UploadFile 支持以下 async 方法,(使用内部 SpooledTemporaryFile)可调用相应的文件方法。
- write(data):把 data (str 或 bytes)写入文件;
- read(size):按指定数量的字节或字符(size (int))读取文件内容;
- seek(offset):移动至文件 offset (int)字节处的位置;
- 例如,await myfile.seek(0) 移动到文件开头;
- 执行 await myfile.read() 后,需再次读取已读取内容时,这种方法特别好用;
- close():关闭文件。
可选文件上传
可以通过使用标准类型注解并将 None 作为默认值的方式将一个文件参数设为可选
async def create_file(file: bytes | None = File(default=None)):
带有额外元数据的 UploadFile
也可以将 File() 与 UploadFile 一起使用,例如,设置额外的元数据
from fastapi import FastAPI, File, UploadFileapp = FastAPI()@app.post("/files/")
async def create_file(file: bytes = File(description="A file read as bytes")):return {"file_size": len(file)}@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(description="A file read as UploadFile"),
):return {"filename": file.filename}
这里File(…)用于配置额外元数据和验证规则
多文件上传
FastAPI 支持同时上传多个文件。
可用同一个「表单字段」发送含多个文件的「表单数据」。
上传多个文件时,要声明含 bytes 或 UploadFile 的列表(List)
@app.post("/files/")
async def create_files(files: list[bytes] = File()):return {"file_sizes": [len(file) for file in files]}@app.post("/uploadfiles/")
async def create_upload_files(files: list[UploadFile]):return {"filenames": [file.filename for file in files]}
请求表单与文件
FastAPI 支持同时使用 File 和 Form 定义文件和表单字段
from fastapi import FastAPI, File, Form, UploadFileapp = FastAPI()@app.post("/files/")
async def create_file(file: bytes = File(), fileb: UploadFile = File(), token: str = Form()
):return {"file_size": len(file),"token": token,"fileb_content_type": fileb.content_type,}