Express-validator no validando después de la función de multer

Tengo un formulario en mi solicitud expresa para que los usuarios introduzcan algún texto, y también suban 1-3 fotos. Estoy manejando el archivo carga en mi cubo S3 con multer, y valido el resto del formulario con validador expreso.

Esto hace que mi ruta POST parezca:

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
  });
});

Estoy teniendo problemas para integrar el validador expreso. He estado atrapado en este problema por unos días, y creo que me estoy acercando. Mi código de abajo atrapará el error de multer, y creará un nuevo Producto si todas las entradas están llenadas. Así que lo que está sucediendo es que mi validador expreso no está captando los errores aquí si (!errors.isEmpty()) { // manejar errores y su simplemente saltando y yendo directo a otra { dejar producto = nuevo producto({. Lo sé porque cuando dejo las entradas vacías, arroja un error mongoose de caminos de esquema perdidos.

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");
      });
    }
  });
});

Realmente apreciaría cualquier ayuda o consejo ya que he estado atrapado en esto por unos días y me siento realmente estúpido!.

Incluiré un bloque final de código, esta es mi función de validación expresa que funciona cuando estoy validando las entradas de texto, así que sé que este enfoque funciona.. Sólo estoy teniendo un momento muy difícil combinando con la función de 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");
      });
    }
  },
];


Pregunta hecha hace 3 años, 5 meses, 0 días - Por codervoyager


2 Respuestas:

  • El problema que estás experimentando es que estás definiendo las reglas de validación en el lugar incorrecto en tu ruta POST. En tu código actual, estás definiendo las reglas de validación dentro de la función de devolución de llamada de la carga única de multer, lo que significa que las reglas de validación no se aplican de manera efectiva.

    Para resolver este problema, debes mover la definición de las reglas de validación fuera de la función de devolución de llamada de multer y colocarlas antes de la función de devolución de llamada principal. De esta manera, las reglas de validación se aplicarán correctamente antes de realizar cualquier procesamiento adicional. Aquí te muestro cómo puedes reorganizar tu código:

    javascript
    router.post("/list-product", listLimiter, 
      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) {
        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 {
          singleUpload(req, res, function (err) {
            if (err) {
              res.redirect("list-product?error=Image error, please make sure your file is JPG or PNG");
              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,
              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");
            });
          });
        }
      }
    );
    

    Con esta reorganización, primero se aplicarán las reglas de validación a los datos del formulario antes de llamar a la función de carga única de multer. De esta manera, tus datos serán validados correctamente antes de continuar con el procesamiento de la carga de archivos. Espero que esto resuelva tu problema, ¡buena suerte!

    Respondida el Dec 18, 2020 a las 00:14 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El problema es que estás llamando a next() dentro del controlador de tu ruta, lo cual es incorrecto. Cuando llamas a next(), estás pasando el control al siguiente middleware en la pila. En tu caso, no hay más middleware, por lo que se está lanzando un error.

    Para resolver este problema, debes eliminar la llamada a next() dentro del controlador de tu ruta. El código corregido debería verse así:

    js
    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
    
        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);
            }
            res.redirect("/list-product");
          });
        }
      });
    });
    

    Con este cambio, si la validación falla, se mostrarán los errores en la página de la lista y el usuario podrá corregirlos. Si la validación tiene éxito, se creará un nuevo producto.

    Respondida el Dec 18, 2020 a las 00:24 - por Gemini

    Votos positivos: 0 | Votos negativos: 0