使用Multer与Express Validator时req.files和req.body未定义问题
问题根源与修复方案
你的代码核心问题是重复执行了Multer的文件上传处理逻辑,导致请求体数据流被二次消费,最终req.files和req.body变为undefined。
具体问题点
路由定义中已经将uploadDocs作为中间件挂载:
router.post('/addDOoc', uploadDocs, docSizeErrhandler, checkSchema(data), (req, res) => { ... })
但在路由回调函数内部,你又再次调用了uploadDocs(req, res, function (err) { ... })。Multer处理文件上传时会读取multipart/form-data格式的请求数据流,这个流只能被消费一次,第二次调用时数据流已经耗尽,自然无法获取到文件和表单数据。
修复后的完整代码
/*schema for validation*/ var data = { 'first_name': { notEmpty: true, errorMessage: "first name is required", isAlpha: true, errorMessage: 'first name must contain only alphabates', trim: true, escape: true }, 'last_name': { notEmpty: true, errorMessage: "last name is required", isAlpha: true, errorMessage: 'last name must contain only alphabates', trim: true, escape: true }, 'address': { notEmpty: true, errorMessage: "address is required", }, 'email': { notEmpty: true, errorMessage: "email id is required", isEmail: true, errorMessage: 'Enter Valid email', normalizeEmail: true, trim: true, escape: true }, 'mbl_num': { notEmpty: true, errorMessage: "mobile number is required", isInt: true, errorMessage: 'mobile number must contain only numbers', } } var maxSize = 3 * 1000 * 1000;//3mb var DIR = './uploads/new/'; //uploads user documents folder let docstorage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, DIR); }, filename: (req, file, cb) => { cb(null, file.fieldname + '-' + Date.now() + '.pdf'); } }); /*upload function*/ var uploadDocs = multer({ storage: docstorage, limits: { fileSize: maxSize }, fileFilter: function (req, file, cb) { let file_name = file.originalname; let file_ext = file_name.split('.')[1]; if (file.mimetype == 'application/pdf' && file_ext == 'pdf') { cb(null, true) } else { req.fileTypeInvalid = 'only pdf are allowed'; cb(new Error('Invalid file type')); } } }).array('files', 12) // 统一处理Multer上传错误 const handleUploadErrors = (err, req, res, next) => { if (err) { if (req.fileTypeInvalid) { return res.status(406).send({ errMsg: req.fileTypeInvalid }); } if (err.code === 'LIMIT_FILE_SIZE') { return res.status(406).send({ Apimessage: 'File size exceeds 3MB limit' }); } return res.status(406).send({ Apimessage: 'Select Valid File' }); } next(); } router.post('/addDOoc', uploadDocs, handleUploadErrors, checkSchema(data), (req, res) => { // 直接获取验证结果,无需重复调用uploadDocs const errors = validationResult(req); if (!errors.isEmpty()) { console.log('validation errors:', errors); return res.status(400).send({ code: 1, msg: 'Incorrect Data' }); } // 此时req.files和req.body已正常填充 console.log('req files--', req.files); console.log('bodyData', req.body); // 后续业务逻辑写在这里 res.status(200).send({ msg: 'Data submitted successfully' }); });
关键修复说明
- 移除重复的uploadDocs调用:路由中间件已经完成文件上传处理,回调内无需再次执行
- 统一错误处理:将文件上传的错误处理整合到单独的中间件
handleUploadErrors中,逻辑更清晰 - 保留正确的中间件顺序:文件上传(
uploadDocs) → 上传错误处理 → 表单校验(checkSchema),确保校验时能获取到完整的表单和文件数据
内容的提问来源于stack exchange,提问作者sangRam
相关产品推荐
相关产品推荐

