FastAPI动态表单多文件上传时Starlette FormData仅返回文件名如何解决
问题根源与解决方案
第一步:修复前端表单编码属性
你遇到的str类型报错绝大多数是前端表单未配置正确的编码格式导致的:
- 表单必须显式添加
enctype="multipart/form-data"属性,否则浏览器默认使用application/x-www-form-urlencoded编码,只会把文件名作为普通字符串提交,不会传输文件二进制内容
示例正确的表单写法:
<form action="/modules/function" method="post" enctype="multipart/form-data"> <!-- 动态生成的文件输入框,name可以重复或者用自定义前缀识别 --> <input type="file" name="upload_file_1"> <input type="file" name="upload_file_2"> <button type="submit">提交</button> </form>
如果是用Fetch/axios等JS动态提交,也要保证构造的FormData对象直接传入请求体,不要手动转成JSON或者其他格式。
第二步:后端动态读取所有上传文件
不需要提前声明参数,直接遍历request.form()拿到的表单数据,筛选所有UploadFile类型的字段即可,适配任意数量的动态上传文件:
from fastapi import FastAPI, Request from starlette.datastructures import UploadFile app = FastAPI() @app.post("/modules/function") async def function(request: Request): form = await request.form() upload_files = [] # 遍历所有表单字段 for field_name, field_value in form.multi_items(): # 只筛选类型为UploadFile的字段,自动跳过普通字符串表单字段 if isinstance(field_value, UploadFile): # 读取文件内容,也可以直接保存到磁盘 filename = field_value.filename content = await field_value.read() upload_files.append({"filename": filename, "content": content}) # 读完记得关闭文件对象释放资源 await field_value.close() # 后续处理逻辑,返回结果示例 return {"uploaded_count": len(upload_files), "filenames": [f["filename"] for f in upload_files]}
补充说明
如果表单有多个同名的文件上传字段,用form.getlist("upload_file")可以直接拿到该字段下所有的UploadFile对象列表,不需要全量遍历:
# 多个文件用同一个name属性的场景 files = form.getlist("upload_file") for file in files: if isinstance(file, UploadFile): content = await file.read() # 处理逻辑
内容的提问来源于stack exchange,提问作者Alvin Wanda
相关产品推荐
相关产品推荐

