FastAPI中如何同时实现Pydantic参数验证与UploadFile文件上传
问题原因
当接口参数包含
File/UploadFile类型时,FastAPI会自动将请求的Content-Type识别为multipart/form-data,这种数据格式不支持直接传递JSON结构的Pydantic模型参数,因此你原来的写法会抛出value is not a valid dict的错误。
注意所有解决方案都需要先安装依赖:pip install python-multipart,请求必须使用multipart/form-data格式提交,不能用application/json
解决方案1:拆分Pydantic字段为Form参数(适合字段少的场景)
直接把Pydantic模型的字段拆成独立的Form参数,手动实例化模型做校验:
from fastapi import Form, UploadFile, File from pydantic import BaseModel class User(BaseModel): user: str name: str @router.post("/upload") async def create_upload_file( user: str = Form(...), name: str = Form(...), file: UploadFile = File(...) ): # 原有Pydantic校验规则完全生效 data = User(user=user, name=name) print(data) return {"filename": file.filename}
调用时直接在form-data里添加user、name、file三个字段提交即可。
解决方案2:Pydantic模型直接适配Form(适合字段多的场景)
FastAPI 0.95及以上版本支持通过Depends直接让Pydantic模型接收Form参数,不需要逐个拆分字段:
from fastapi import Form, UploadFile, File, Depends from pydantic import BaseModel class User(BaseModel): user: str name: str @classmethod def as_form(cls, user: str = Form(...), name: str = Form(...)): return cls(user=user, name=name) @router.post("/upload") async def create_upload_file( data: User = Depends(User.as_form), file: UploadFile = File(...) ): print(data) return {"filename": file.filename}
原有Pydantic的所有校验逻辑不需要修改,调用方式和方案1完全一致。
解决方案3:JSON字符串转模型(仅特殊场景使用)
如果前端必须传递结构化JSON,可以把JSON序列化成字符串放在Form字段里,后端手动解析:
import json from fastapi import Form, UploadFile, File, RequestValidationError from pydantic import BaseModel class User(BaseModel): user: str name: str @router.post("/upload") async def create_upload_file( data_str: str = Form(...), file: UploadFile = File(...) ): try: data = User.parse_raw(data_str) except json.JSONDecodeError: raise RequestValidationError("data_str字段不是合法JSON格式") print(data) return {"filename": file.filename}
调用时把用户数据序列化为JSON字符串,放在form-data的data_str字段提交即可。
内容的提问来源于stack exchange,提问作者Alexander Vedmed'
相关产品推荐
相关产品推荐

