Postman发送form-data POST请求报'name' is required,Joi校验异常求解
问题原因
核心问题是Express中间件执行顺序错误,搭配Joi校验函数的逻辑缺陷共同触发了报错:
- form-data格式的请求体无法被Express默认的body-parser解析,必须依赖multer的
upload系列中间件解析完成后,普通表单字段才会挂载到req.body对象上。你当前路由的中间件顺序是validateProduct在前、upload.single("productImage")在后,执行Joi校验时req.body还处于空值状态,自然会触发name字段必填的校验错误。 - 你贴出的
validateProduct函数不符合Express中间件的规范:既没有正确从req.body中获取待校验的数据,也没有实现校验通过调用next()放行、校验失败返回错误的逻辑,本身就无法正常完成校验工作。
解决方案
按照以下两步调整即可解决问题:
- 调整路由的中间件顺序,把multer解析逻辑放到Joi校验前面,先解析出
req.body字段再做校验 - 补全
validateProduct的中间件逻辑,正确实现Joi校验流程
修正后的代码示例如下:
// 模型文件的校验函数修正为标准Express中间件格式 function validateProduct(req, res, next) { const schema = Joi.object({ name: Joi.string().min(3).required(), price: Joi.number().min(0).required(), quantity: Joi.number().min(0).required(), }); // 校验req.body中的字段 const { error } = schema.validate(req.body); if (error) { return res.status(400).send(error.details[0].message); } // 校验通过放行到下一个中间件 next(); }
// 接口文件调整中间件执行顺序 router.post( "/", upload.single("productImage"), // 先执行multer解析form-data validateProduct, // 解析完成后再执行Joi校验 async (req, res) => { console.log(req.file); let product = await Product.findOne({ name: req.body.name }); if (product) return res.status(400).send("Product with same name already exist!"); product = new Product(); product.name = req.body.name; product.price = req.body.price; product.quantity = req.body.quantity; await product.save(); return res.send(product); } );
如果调整后仍然报错,可检查Postman中form-data的字段名拼写是否和校验规则一致,不要添加多余的前后空格。
内容的提问来源于stack exchange,提问作者Soman Talha
相关产品推荐
相关产品推荐

