FastAPI中如何传递带索引的多组文件及附加JSON数据
FastAPI 动态分组文件+JSON数据传递解决方案
问题原因
你之前的写法无法获取node_files是因为FastAPI没有内置规则自动将multipart/form-data中的动态文件字段映射到Dict[str, List[UploadFile]]类型参数上,Depends(lambda: {})仅提供空字典默认值,不会触发文件解析逻辑。此外,同时使用Body(...)接收JSON和文件上传会冲突——文件上传要求请求为multipart/form-data格式,而Body默认期望application/json格式。
实现方案
下面给出两种可行的实现方式,核心思路是通过multipart/form-data传递JSON字符串和分组文件,后端手动解析表单数据完成文件分组:
方案一:手动解析请求表单(推荐,适配动态节点)
from fastapi import FastAPI, Request, Form, UploadFile from typing import Dict, List import json app = FastAPI() @app.post("/process") async def process( request: Request, data: str = Form(...) # JSON数据以字符串形式放在form字段中 ): # 解析JSON数据 json_payload = json.loads(data) # 初始化分组文件字典 node_files: Dict[str, List[UploadFile]] = {} # 读取整个表单数据 form_data = await request.form() # 遍历表单字段,按节点ID分组文件 for field_name, value in form_data.items(): # 约定字段名格式为 node_{节点ID},例如 node_1、node_2 if field_name.startswith("node_"): node_id = field_name.split("_")[1] if isinstance(value, UploadFile): # 节点ID不存在则初始化列表 if node_id not in node_files: node_files[node_id] = [] node_files[node_id].append(value) # 业务处理示例:读取文件内容 for node_id, files in node_files.items(): for file in files: content = await file.read() # 此处可添加文件保存、数据处理等逻辑 print(f"节点 {node_id} 的文件: {file.filename}, 大小: {len(content)} bytes") return { "status": "success", "received_json": json_payload, "node_file_stats": {node_id: len(files) for node_id, files in node_files.items()} }
Postman测试步骤
- 请求方法选择
POST,URL填写http://localhost:8000/process - 切换到
Body标签,选择form-data格式 - 添加字段
data,类型选Text,值填入你的JSON字符串(例如{"graph": {"nodes": [{"id": "1"}, {"id": "2"}]}}) - 添加文件字段:
- 字段名按
node_1、node_1(同一个字段名可重复添加多个文件)、node_2等格式命名 - 每个文件字段类型选
File,选择要上传的文件
- 字段名按
- 发送请求,后端即可正确接收分组文件和JSON数据
方案二:固定节点字段(仅适用于节点数量固定的场景)
如果你的节点ID是可预知的固定值,可以直接声明对应字段,FastAPI会自动解析同名字段的多个文件:
from fastapi import FastAPI, Form, UploadFile from typing import List import json app = FastAPI() @app.post("/process-fixed") async def process_fixed( data: str = Form(...), node_1: List[UploadFile] = Form([]), # 节点1的文件,默认空列表 node_2: List[UploadFile] = Form([]) # 节点2的文件,默认空列表 ): json_payload = json.loads(data) # 业务处理逻辑 return { "status": "success", "received_json": json_payload, "node_1_files_count": len(node_1), "node_2_files_count": len(node_2) }
关键注意事项
- 禁止同时使用
Body(...)和文件上传,必须将JSON数据放在form-data的文本字段中 - 动态节点场景下,需通过约定字段名格式(如
node_{节点ID})来实现文件分组,后端手动解析 - 同节点的多个文件需使用相同的字段名上传,FastAPI会自动将其解析为
List[UploadFile]
内容的提问来源于stack exchange,提问作者jereesh thomas
相关产品推荐
相关产品推荐

