Node.js 快速验证程序在multer函数后未执行

Node.js 快速验证程序在multer函数后未执行,node.js,express,mongoose,multer,express-validator,Node.js,Express,Mongoose,Multer,Express Validator,我在我的express应用程序中有一个表单,用户可以输入一些文本,还可以上传1-3张照片。我用multer处理文件上传到S3存储桶的过程,用expressvalidator验证表单的其余部分 这使我的发布路线看起来像: router.post("/list-product", listLimiter, function (req, res) { singleUpload(req, res, function (err) { // if any multer err

我在我的express应用程序中有一个表单,用户可以输入一些文本,还可以上传1-3张照片。我用multer处理文件上传到S3存储桶的过程,用
expressvalidator
验证表单的其余部分

这使我的发布路线看起来像:

router.post("/list-product", listLimiter, function (req, res) {
  singleUpload(req, res, function (err) {
    // if any multer errors, redirect to form
    if (err) {
      res.redirect(
        "list-product" +
          "?error=Image error, please make sure your file is JPG or PNG"
      );
      return;
    }
    // if no multer errors, validate rest of form
  });
});
我在集成
express validator
时遇到问题。我已经在这个问题上纠缠了好几天了,我想我快要解决了。我下面的代码将捕获multer错误,如果填写了所有输入,它将创建一个新的
产品。所以现在发生的是我的
express验证器
没有在这里捕获错误
if(!errors.isEmpty()){//handle errors
,它只是跳过它,直接转到
else{let product=new product({
)。我知道这一点,因为当我将输入留空时,它会抛出一个丢失模式路径的mongoose错误

let upload = require("../controllers/uploadController");
const singleUpload = upload.single("image");


router.post("/list-product", listLimiter, function (req, res, next) {
  singleUpload(req, res, function (err) {
    // if any multer errors, redirect to form
    if (err) {
      res.redirect(
        "list-product" +
          "?error=Image error, please make sure your file is JPG or PNG"
      );
      return;
    }
    // if no multer errors, validate rest of form

    body("productName")
      .trim()
      .isLength({ min: 1 })
      .withMessage("Please enter the name of your product"),
      body("productPrice")
        .isNumeric()
        .withMessage("Please enter a valid price"),
      body("productCategory")
        .trim()
        .isLength({ min: 1 })
        .withMessage("Please select the category of your product"),
      body("productDescription")
        .trim()
        .isLength({ min: 50 })
        .withMessage("Minimum 50 characters")
        .isLength({ max: 500 })
        .withMessage("Maximum 500 characters"),
      body("businessName")
        .trim()
        .isLength({ min: 1 })
        .withMessage("Please enter the name of your business"),
      body("website")
        .trim()
        .isURL()
        .withMessage("Please enter the URL for your product or business");

    check("*").escape();

    const errors = validationResult(req);
    let errArray = errors.array();

    if (!errors.isEmpty()) {
      res.render("list", {
        form: req.body,
        errors: errArray,
        msg: "Please check the form for errors",
        option: req.body.productCategory,
      });
      return;
    } else {
      let product = new Product({
        business: req.body.businessName,
        productName: req.body.productName,
        category: req.body.productCategory,
        price: req.body.productPrice,
        description: req.body.productDescription,
        website: req.body.website,
        imageURL:
          "https://mybucket.s3-us-west-2.amazonaws.com/" + req.imageName,
        imageURL2:
          "https://mybucket.s3-us-west-2.amazonaws.com/" + req.imageName,
      });
      product.save(function (err) {
        if (err) {
          console.log(err);
          return next(err);
        }
        res.redirect("/list-product");
      });
    }
  });
});
我真的很感激任何帮助或建议,因为我已经被困在这几天了,我觉得自己真的很愚蠢

我将包括最后一块代码,这是我的
express validator
函数,当我验证文本输入时,它会工作,所以我知道这种方法确实有效。我只是很难将它与multer函数结合起来

exports.list__post = [
  body("productName")
    .trim()
    .isLength({ min: 1 })
    .withMessage("Please enter the name of your product"),
  body("productPrice")
    .isNumeric()
    .withMessage("Please enter a valid price"),
  body("productCategory")
    .trim()
    .isLength({ min: 1 })
    .withMessage("Please select the category of your product"),
  body("productDescription")
    .trim()
    .isLength({ min: 50 })
    .withMessage("Minimum 50 characters")
    .isLength({ max: 500 })
    .withMessage("Maximum 500 characters"),
  body("businessName")
    .trim()
    .isLength({ min: 1 })
    .withMessage("Please enter the name of your business"),
  body("website")
    .trim()
    .isURL()
    .withMessage("Please enter the URL for your product or business"),

  check("*").escape(),

  (req, res, next) => {
    const errors = validationResult(req);
    let errArray = errors.array();

    if (!errors.isEmpty()) {
      console.log(req.body)
      res.render("list", {
        form: req.body,
        errors: errArray,
        msg: "Please check the form for errors",
        option: req.body.productCategory,
      });
      return;
    } else {
      
      let product = new Product({
        business: req.body.businessName,
        productName: req.body.productName,
        category: req.body.productCategory,
        price: req.body.productPrice,
        description: req.body.productDescription,
        website: req.body.website,
        imageURL: "https://mybucket.s3-us-west-2.amazonaws.com/" + req.imageName,
        imageURL2:"https://mybucket.s3-us-west-2.amazonaws.com/" + req.imageName,
      });
      product.save(function (err) {
        if (err) {
          console.log(err);
          return next(err);
        }
        res.redirect("/list-product");
      });
    }
  },
];
更新:

// uploadController.js

const aws = require("aws-sdk");
const multer = require("multer");
const multerS3 = require("multer-s3");
const crypto = require("crypto");
require("dotenv").config();

// config aws
aws.config.update({
  secretAccessKey: process.env.SECRETACCESSKEY,
  accessKeyId: process.env.ACCESSKEYID,
  region: "us-west-2",
});
const s3 = new aws.S3();

const fileFilter = (req, file, cb) => {
  if (file.mimetype === "image/jpeg" || file.mimetype === "image/png") {
    cb(null, true);
  } else {
    cb(new Error("Invalid format, only JPG and PNG"), false);
  }
};

const upload = multer({
  fileFilter: fileFilter,
  limits: { fileSize: 1024 * 1024 },
  storage: multerS3({
    s3: s3,
    bucket: "mybucket",
    acl: "public-read",
    metadata: function (req, file, cb) {
      cb(null, { fieldName: file.fieldname });
    },
    key: function (req, file, cb) {
      req.imageName = crypto.randomBytes(16).toString("hex");
      cb(null, req.imageName);
    },
  }),
});

module.exports = upload;


快速修复:

  • 在中间件中调用
    singleUpload
    ,这里您使用
    upload.single()
    上载单个文件,因此您需要从视图文件标记中删除
    multiple
    属性,如果您要上载多个文件,则使用
    upload.array('field name',文件总数)
  • 验证中间件中的其他参数
  • 我注意到您没有在表单中添加
    businessName
    字段,因此这将返回错误,您可以在表单中添加它,也可以在模式中删除验证
  • 中间件回调函数,此处
    req
    将提供上传的所有主体参数和文件对象
  • 只要控制台
    req.body
    并使用
    req.file
    将返回S3中上载的文件的所有详细信息,包括文件名和位置,我建议您使用此对象的文件名和位置,我已经有控制台了
  • 使用我们从fileFitler传递的
    req.fileTypeInvalid
    处理文件扩展名错误

请求的合并最终版本:

router.post(“/list product”,
单上传,
[
body(“productName”).trim().isLength({min:1}).withMessage(“请输入产品名称”),
正文(“productPrice”).isNumeric().withMessage(“请输入有效价格”),
body(“productCategory”).trim().isLength({min:1}).withMessage(“请选择产品的类别”),
body(“productDescription”).trim().isLength({min:50}).withMessage(“最少50个字符”).isLength({max:500}).withMessage(“最多500个字符”),
body(“businessName”).trim().isLength({min:1}).withMessage(“请输入您的企业名称”),
正文(“网站”).trim().isURL().withMessage(“请输入您的产品或业务的URL”),
勾选(“*”).escape()
], 
功能(req、res、next){
日志(req.body,req.file);
//文件扩展名错误
如果(请求文件类型无效){
res.redirect(“列出产品“+”?错误=图像错误,请确保您的文件是JPG或PNG”);
返回;
}
常量错误=验证结果(req);
如果(!errors.isEmpty()){
设errArray=errors.array();
让errorsObj={};//单独访问错误
勘误表.地图((项目)=>{
const id=item.param;
删除item.param;
errorsObj[id]=物料;
});
res.render(“列表”{
表格:要求正文,
错误:errorsObj,
msg:“请检查表单是否有错误”,
选项:req.body.productCategory,
});
返回;
}
让产品=新产品({
业务:req.body.businessName,
productName:req.body.productName,
类别:req.body.productCategory,
价格:req.body.productPrice,
描述:req.body.productDescription,
网站:req.body.website,
图像URL:“https://mybucket.s3-us-west-2.amazonaws.com/“+req.imageName,
});
product.save(函数(err){
如果(错误){
控制台日志(err);
返回下一个(错误);
}
res.redirect(“/列出产品”);
});
});
router.post("/list-product", 
  singleUpload, 
  [
    body("productName").trim().isLength({ min: 1 }).withMessage("Please enter the name of your product"),
    body("productPrice").isNumeric().withMessage("Please enter a valid price"),
    body("productCategory").trim().isLength({ min: 1 }).withMessage("Please select the category of your product"),
    body("productDescription").trim().isLength({ min: 50 }).withMessage("Minimum 50 characters").isLength({ max: 500 }).withMessage("Maximum 500 characters"),
    body("businessName").trim().isLength({ min: 1 }).withMessage("Please enter the name of your business"),
    body("website").trim().isURL().withMessage("Please enter the URL for your product or business"),
    check("*").escape()
  ], 
  function (req, res, next) {
    console.log(req.body, req.file);

    // FILE EXTENSION ERROR
    if (req.fileTypeInvalid) {
        res.redirect("list-product" + "?error=" + req.fileTypeInvalid);
        return;
    }

    const errors = validationResult(req);
    if (!errors.isEmpty()) {
        let errArray = errors.array();
        let errorsObj = {}; // access errors indiviually 
        errArray.map((item) => {
            const id = item.param;
            delete item.param;
            errorsObj[id] = item;
        });
        res.render("list", {
            form: req.body,
            errors: errorsObj,
            msg: "Please check the form for errors",
            option: req.body.productCategory,
        });
        return;
    }

    let product = new Product({
        business: req.body.businessName,
        productName: req.body.productName,
        category: req.body.productCategory,
        price: req.body.productPrice,
        description: req.body.productDescription,
        website: req.body.website,
        imageURL: "https://mybucket.s3-us-west-2.amazonaws.com/" + req.imageName,
    });
    product.save(function (err) {
        if (err) {
            console.log(err);
            return next(err);
        }
        res.redirect("/list-product");
    });
});