如何用Axios在Node.js中调用FastAPI多表单数据接口?
解决Axios调用FastAPI表单接口422错误的方案
核心问题原因
422错误源于Axios 0.21版本处理FormData数组的默认行为和FastAPI的解析规则不匹配:
- FastAPI接收
List[str]类型的names/surnames时,要求表单中同一个key重复出现(如names=张三&names=李四) - 旧版Axios会自动给数组key添加
[]后缀(变成names[]=张三),导致FastAPI无法识别参数格式 - 多文件上传需要逐个将文件实例绑定到对应key,不能批量传递文件数组
正确的Node.js Axios实现代码
const axios = require('axios'); const FormData = require('form-data'); const fs = require('fs'); async function invokeParseAPI() { const form = new FormData(); // 处理names数组:逐个追加,保持key为'names' ['张三', '李四'].forEach(name => { form.append('names', name); }); // 处理surnames数组:同上逻辑 ['王', '赵'].forEach(surname => { form.append('surnames', surname); }); // 处理references多文件:逐个读取并追加,key保持'references' ['./ref1.pdf', './ref2.txt'].forEach(path => { form.append('references', fs.createReadStream(path), { filename: path.split('/').pop() // 确保后端能获取正确文件名 }); }); // 处理choices多文件:同上逻辑 ['./choice1.jpg', './choice2.png'].forEach(path => { form.append('choices', fs.createReadStream(path), { filename: path.split('/').pop() }); }); try { const res = await axios.post('http://localhost:8086/parse', form, { headers: form.getHeaders() // 必须使用FormData生成的请求头,包含正确的边界符 }); console.log('请求成功:', res.data); } catch (err) { console.error('请求失败:', err.response?.data || err.message); } } invokeParseAPI();
关键注意点
- 数组参数处理:绝对不能直接给
form.append传数组,必须循环逐个追加,避免Axios自动添加[]后缀 - 文件上传细节:使用
fs.createReadStream读取文件,必须指定filename参数,FastAPI依赖文件名识别UploadFile实例 - 请求头设置:禁止手动设置
Content-Type: multipart/form-data,必须用form.getHeaders()生成完整请求头(包含边界分隔符) - 版本兼容:Node.js 10.19.0和Axios 0.21版本完全适配上述代码,无需升级依赖
后端FastAPI端点验证(确保参数名匹配)
确认你的FastAPI端点定义如下,参数名必须和前端FormData的key完全一致:
from fastapi import FastAPI, UploadFile, File, Form from typing import List app = FastAPI() @app.post("/parse") async def parse_endpoint( names: List[str] = Form(...), surnames: List[str] = Form(...), references: List[UploadFile] = File(...), choices: List[UploadFile] = File(...) ): return { "received_names": names, "received_surnames": surnames, "reference_files_count": len(references), "choice_files_count": len(choices) }
内容的提问来源于stack exchange,提问作者rrrttt
相关产品推荐
相关产品推荐

