You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建可接受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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 03:30:57