如何创建可接受File/Form或JSON请求体的FastAPI端点?
实现FastAPI端点兼容JSON与multipart/form-data请求
你可以通过两种方式实现需求:一是检测请求的Content-Type头来分别处理不同类型的请求体,二是通过依赖项统一解析逻辑。以下是具体实现方案:
方案一:检测请求类型并分别处理
通过Request对象获取请求头中的Content-Type,判断当前请求是JSON还是multipart/form-data,再对应解析数据:
from fastapi import FastAPI, Request, Form, File, UploadFile from pydantic import BaseModel from typing import Optional app = FastAPI() class Item(BaseModel): name: str description: Optional[str] = None @app.post("/process") async def process_request( request: Request, file: Optional[UploadFile] = File(None), name: Optional[str] = Form(None), description: Optional[str] = Form(None) ): content_type = request.headers.get("Content-Type") if not content_type: return {"error": "Missing Content-Type header"} if "application/json" in content_type: # 解析JSON请求体 json_data = await request.json() item = Item(**json_data) elif "multipart/form-data" in content_type: # 解析form-data表单数据 if not name: return {"error": "Missing 'name' field in form-data"} item = Item(name=name, description=description) # 处理上传的文件(如果有) file_info = file.filename if file else None else: return {"error": "Unsupported Content-Type. Use application/json or multipart/form-data"} response = {"received_item": item.dict()} if "file_info" in locals(): response["uploaded_file"] = file_info return response
方案二:用依赖项统一解析逻辑
将请求解析逻辑封装为依赖函数,让端点代码更简洁:
from fastapi import FastAPI, Depends, Request, Form, File, UploadFile from pydantic import BaseModel from typing import Optional app = FastAPI() class Item(BaseModel): name: str description: Optional[str] = None async def parse_request(request: Request, name: Optional[str] = Form(None), description: Optional[str] = Form(None)) -> Item: content_type = request.headers.get("Content-Type") if "application/json" in content_type: return Item(**await request.json()) elif "multipart/form-data" in content_type: if not name: raise ValueError("'name' field is required in form-data") return Item(name=name, description=description) else: raise ValueError("Unsupported Content-Type") @app.post("/process") async def process_request(item: Item = Depends(parse_request), file: Optional[UploadFile] = File(None)): response = {"item": item.dict()} if file: response["uploaded_file"] = file.filename return response
注意事项
- 判断
Content-Type时用包含判断(in),因为multipart/form-data请求通常会带boundary参数(如multipart/form-data; boundary=----WebKitFormBoundaryxxx)。 - 若form-data的字段名与JSON模型字段不一致,需在
Form参数中做映射(比如Form(None, alias="form_field_name"))。 - JSON请求无法直接传递文件,文件上传仅支持multipart/form-data格式,因此
File参数需设为可选。
内容的提问来源于stack exchange,提问作者STY
相关产品推荐
相关产品推荐

