FormData无法添加文件至后端问题排查求助
问题:FormData文件无法发送至后端,后端req.body为空、req.files未定义
初始问题:使用console.log(formData.entries())查看时结果为空,后端接收不到文件,文件变量已存在但无法追加到FormData。
更新:通过for循环能看到FormData内容,但后端req.body显示{},req.files为undefined。
前端代码
async function handleMultipleSubmit(event) { const formData = new FormData(); console.log(files); files.forEach((file, index) => { console.log(file); formData.append(`file${index}`, file); }); for (const [ key, value] of formData.entries()) { console.log(key, value); } await axios .post("/api/farmers/csv", formData) .then((response) => { if (response.data.success) { console.log(response.data.results); } else { console.log(response); } }) .catch((error) => { console.log(error); }); } if (files.length > 0) { handleMultipleSubmit(); } }, [files]);
请求控制台说明
控制台打印显示FormData中已包含多个文件项,键为file0、file1等,对应正常的文件对象。
后端代码
const multer = require("multer"); const fs = require("fs"); const path = require("path"); // 配置multer存储路径和文件名 const storage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, "uploads/"); }, filename: (req, file, cb) => { cb(null, Date.now() + "-" + file.originalname); }, }); // 创建multer上传实例 const upload = multer({ storage: storage }); // 自定义文件上传中间件 exports.uploadMiddleware = (req, res, next) => { console.log(req); console.log(req.body); console.log(req.files); // 使用multer上传实例 upload.array("files", 5)(req, res, (err) => { if (err) { return res.status(400).json({ error: err.message }); } // 获取上传的文件 const files = req.files; const errors = []; console.log(files); // 验证文件类型和大小 files.forEach((file) => { const allowedTypes = ["text/csv"]; const maxSize = 5 * 1024 * 1024; // 5MB if (!allowedTypes.includes(file.mimetype)) { errors.push(`无效文件类型: ${file.originalname}`); } if (file.size > maxSize) { errors.push(`文件过大: ${file.originalname}`); } }); // 处理验证错误 if (errors.length > 0) { // 删除已上传的文件 files.forEach((file) => { fs.unlinkSync(file.path); }); return res.status(400).json({ errors }); } // 将文件附加到请求对象 req.files = files; // 进入下一个中间件或路由处理程序 next(); }); };
解决方法
1. 统一前后端文件字段名
后端用upload.array("files", 5)表示要接收键名为files的多文件,但前端用file${index}作为键名,导致multer无法识别。修改前端追加文件的代码:
files.forEach((file) => { formData.append("files", file); });
2. 禁止手动设置Axios的Content-Type
Axios会自动为FormData请求生成带boundary的multipart/form-data请求头,手动设置会丢失boundary,导致后端无法解析。当前代码无需额外修改,保持默认即可。
3. 调整后端中间件打印时机
当前在multer解析请求前就打印req.body和req.files,此时还未完成解析,必然为空。把打印代码移到multer解析之后:
exports.uploadMiddleware = (req, res, next) => { // 使用multer上传实例 upload.array("files", 5)(req, res, (err) => { if (err) { return res.status(400).json({ error: err.message }); } // 解析完成后再打印 console.log(req.body); console.log(req.files); // 获取上传的文件 const files = req.files; const errors = []; console.log(files); // ... 后续验证代码不变 }); };
4. 确保uploads目录存在
multer指定的uploads/目录如果不存在会报错,在服务启动时自动创建目录:
const uploadDir = path.join(__dirname, "uploads"); if (!fs.existsSync(uploadDir)) { fs.mkdirSync(uploadDir); }
内容的提问来源于stack exchange,提问作者Andrew Vargas
相关产品推荐
相关产品推荐

