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

如何在FastAPI的POST端点中上传文件并传递字典列表参数?

问题:FastAPI POST端点同时上传多文件+字典列表参数报错

场景

需要在同一个FastAPI的POST接口中同时上传多个文件,并且传递字典列表格式的参数,测试代码如下:

from fastapi import FastAPI, File, UploadFile, Body, status
from pydantic import BaseModel, model_validator
from typing import Optional, List
import json

app = FastAPI()


class FileUpload(BaseModel):
    name: str
    header_exists: bool
    rows_to_skip: int


class ListFileUpload(BaseModel):
    data: List[FileUpload]


@app.post("/upload")
async def file_upload(files: List[UploadFile], params: ListFileUpload):
    for file in files:
        print(file)
    print(params)

报错信息(翻译后)

422 不可处理实体
字段params验证失败:值不是有效的字典类型

原因

当接口同时接收文件和复杂结构参数时,请求会以multipart/form-data格式发送,但FastAPI默认无法直接从表单数据中解析嵌套的Pydantic模型(比如包含列表的ListFileUpload),需要显式指定参数的解析方式。

解决方案

有两种可行的处理方式:

方式1:用Body(...)显式标记参数,指定媒体类型

修改接口定义,给params参数加上Body(...),让FastAPI从请求体的表单字段中解析JSON结构:

@app.post("/upload")
async def file_upload(
    files: List[UploadFile] = File(...),
    params: ListFileUpload = Body(..., media_type="application/json")
):
    for file in files:
        print(f"文件名: {file.filename}")
    print(f"参数内容: {params.dict()}")
    return {"files_count": len(files), "params": params.dict()}

方式2:将参数序列化为JSON字符串传递,后端手动解析

如果客户端不方便发送JSON格式的表单字段,可让客户端把参数序列化成JSON字符串,后端手动解析为Pydantic模型:

@app.post("/upload")
async def file_upload(
    files: List[UploadFile] = File(...),
    params_str: str = Body(...)
):
    params = ListFileUpload.parse_raw(params_str)
    for file in files:
        print(f"文件名: {file.filename}")
    print(f"参数内容: {params.dict()}")
    return {"files_count": len(files), "params": params.dict()}

测试示例(curl命令)

方式1测试命令:

curl -X POST "http://localhost:8000/upload" \
  -H "Content-Type: multipart/form-data" \
  -F "files=@file1.csv" \
  -F "files=@file2.csv" \
  -F 'params={"data": [{"name": "file1", "header_exists": true, "rows_to_skip": 1}, {"name": "file2", "header_exists": false, "rows_to_skip": 0}]}'

方式2测试命令:

curl -X POST "http://localhost:8000/upload" \
  -H "Content-Type: multipart/form-data" \
  -F "files=@file1.csv" \
  -F "files=@file2.csv" \
  -F 'params_str="{\"data\": [{\"name\": \"file1\", \"header_exists\": true, \"rows_to_skip\": 1}, {\"name\": \"file2\", \"header_exists\": false, \"rows_to_skip\": 0}]}"'

内容的提问来源于stack exchange,提问作者Tanmay Tete

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 19:02:42