【问题标题】:How to prevent Multer File Upload when input validation fails输入验证失败时如何防止 Multer 文件上传
【发布时间】:2019-09-20 03:37:56
【问题描述】:

我正在创建一个 (POST) 路由来处理文件上传,并且除了文件路径之外,还将一些其他属性存储到 MongoDB。问题是当输入验证失败时,文件仍然上传到 static(uploads) 文件夹中。

我正在使用 Multer 中间件进行文件上传。

设置

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, "./uploads/");
  },
  filename: (req, file, cb) => {
    cb(null, Date.now() + "-" + file.originalname);
  }
});

const fileFilter = (req, file, cb) => {
  if (file.mimetype === "image/jpeg" || file.mimetype === "image/png") {
    cb(null, true);
  } else {
    //rejects storing a file
    cb(null, false);
  }
};

const upload = multer({
  storage: storage,
  limits: {
    fileSize: 1024 * 1024 * 5
  },
  fileFilter: fileFilter
});

字段

const seamUpload = upload.fields([
  { name: "stylePicture", maxCount: 1 },
  { name: "materialPicture", maxCount: 1 }
]);

路线

router.post("/", [auth, seamUpload], async (req, res) => {
  const { error } = validateSeam(req.body);
  if (error) return res.status(400).send(error.details[0].message);

  const seam = new Seam({
    stylePicture: req.files["stylePicture"][0].path,
    materialPicture: req.files["materialPicture"][0].path,
    description: req.body.description,
    deliveryDate: req.body.deliveryDate,
    customer: req.body.customerId
  });

  await seam.save();

  res.send(seam);
});

Client(PostMan) Screenshot

【问题讨论】:

    标签: node.js express multer joi


    【解决方案1】:

    您可以在 multer 中间件之前拥有验证中间件。 这样,当验证失败时,所有后续的中间件都不会被执行——因此,文件也不会被上传。

    像这样分离验证:

    const validateSeamUpload = (req, res, next) => {
        const { error } = validateSeam(req.body);
        if (error) return res.status(400).send(error.details[0].message);
        return next();
    };
    

    然后,像这样在seamUpload 中间件之前安装这个validateSeamUpload

    router.post("/", [auth, validateSeamUpload, seamUpload], async (req, res) => {
        /** No need for validation here as it was already done in validateSeamUpload */
        const seam = new Seam({
            stylePicture: req.files["stylePicture"][0].path,
            materialPicture: req.files["materialPicture"][0].path,
            description: req.body.description,
            deliveryDate: req.body.deliveryDate,
            customer: req.body.customerId
        });
    
        await seam.save();
    
        res.send(seam);
    });
    

    顺便说一句,您也可以将它们作为参数传递给post()。像这样:

    router.post("/", /** => See, no need for an array */ auth, validateSeamUpload, seamUpload, async (req, res) => {
        /** your controller code */
    });
    

    【讨论】:

    • 谢谢,试试这个
    • 您能详细说明一下吗?你提出了什么要求?你用的是哪个客户端?任何相关的代码sn-ps?编辑您的问题以包括所有这些
    • 我向 Seam 端点发出了一个 post 请求,它返回一个验证错误 customerId is required。然后,我尝试在控制台中记录 req.body ,但它是一个空对象。我正在使用 Postman 客户端(类型:表单数据)
    • 但是如果验证错误,文件会被保存吗?
    • 不,它没有
    【解决方案2】:

    当您遇到此问题时,我是我。 我发现的一种解决方案是,当您在所有模式下的身份验证似乎都出现错误时,如果您有来自客户端的文件,您可以像这样轻松删除它:

        if(req.file) {
           fs.unlink(
                 path.join(__dirname, "go to root folder that 'req.file.path' leads to the file", req.file.path),
                    (err) => console.log(err));
        }
    

    或者,如果您有多个文件,您应该对每个文件执行相同的操作。如果有,我很高兴在这里。

    我希望有另一种方法,使用 multer 包来处理。

    祝你好运

    【讨论】:

      猜你喜欢
      • 2022-11-22
      • 1970-01-01
      • 2016-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多