【问题标题】:How to use multer with express.Router()?如何将 multer 与 express.Router() 一起使用?
【发布时间】:2022-09-29 06:14:36
【问题描述】:

我想在我的 nodejs 应用程序中使用 multer 来上传用户个人资料图片。我的路线由快速路由器管理。我检查了很多教程,但没有一个符合我的确切用例。我想让用户将他们的个人资料图片上传到我的 API,但在请求到达上传功能之前,我想执行一些验证,如密码和 API 密钥检查。 这是我的上传控制器,


const multer = require(\"multer\");
const path = require(\"path\");

const dp_storage = multer.diskStorage({
  destination: path.join(__dirname, \"../user_uploads/images/dp\"),
  filename: function (req, file, cb) {
    cb(
      null,
      file.fieldname + \"-\" + Date.now() + path.extname(file.originalname)
    );
  },
});

// Init dp Upload
const dp_upload = multer({
  storage: dp_storage,
  limits: { fileSize: 2000000 }, // 1 mb
  fileFilter: function (req, file, cb) {
    checkFileTypeForUserDP(file, cb);
  },
}).single(\"dp\");

function checkFileTypeForUserDP(file, cb) {
  // Allowed ext
  let filetypes = /jpeg|jpg|png|gif|webp/;
  // Check ext
  let extname = filetypes.test(path.extname(file.originalname).toLowerCase());
  // Check mime
  let mimetype = filetypes.test(file.mimetype);

  if (mimetype && extname) {
    return cb(null, true);
  } else {
    cb(\"Error: jpeg, jpg, png, gif Images Only!\");
  }
}

exports.uploadDP = async (req, res) => {
  try {
    dp_upload(req, res, (err) => {
      if (err) {
        console.log(err);
      } else {
        if (req.file == undefined) {
          res.status(404).json({
            success: false,
            msg: \"File is undefined!\",
            file: `uploads/${req.file.filename}`,
          });
        } else {
          res.status(200).json({
            success: true,
            msg: \"File Uploaded!\",
            file: `uploads/${req.file.filename}`,
          });
        }
      }
    });
  } catch (error) {console.log(error);}
};

如果我在没有任何 API 密钥验证或用户身份验证的情况下直接使用上面的代码,它就可以正常工作。

这是我的路由器,

const express = require(\"express\");
const router = express.Router();
const { authenticateUser ,apiKeyCheck} = require(\"../server\");
const { uploadDP } = require(\"../controllers/file\");

//this route works
router.post(
    \"/upload/dp_without_authentication\",
    uploadDP
);
//this is not working
router.post(
    \"/upload/dp\",
    apiKeyCheck,
    authenticateUser,
    uploadDP
);

module.exports = router;

\"/upload/dp\" 路由失败,因为 apiKeyCheck and authenticateUser 函数无法从 req.body 读取用户凭据。 所以,为了解决这个问题,我在我的主服务器文件中添加了以下几行,

const multer = require(\"multer\");
const upload = multer();
app.use(upload.array());

但是现在 uploadDP 函数甚至没有被调用,而是返回以下错误:

MulterError: Unexpected field
    at wrappedFileFilter (/Users/sujith/Documents/Personal_projects/VocabularyServer/node_modules/multer/index.js:40:19)
    at Busboy.<anonymous> (/Users/sujith/Documents/Personal_projects/VocabularyServer/node_modules/multer/lib/make-middleware.js:115:7)
    at Busboy.emit (node:events:394:28)
    at Busboy.emit (/Users/sujith/Documents/Personal_projects/VocabularyServer/node_modules/busboy/lib/main.js:38:33)
    at PartStream.<anonymous> (/Users/sujith/Documents/Personal_projects/VocabularyServer/node_modules/busboy/lib/types/multipart.js:213:13)
    at PartStream.emit (node:events:394:28)
    at HeaderParser.<anonymous> (/Users/sujith/Documents/Personal_projects/VocabularyServer/node_modules/busboy/node_modules/dicer/lib/Dicer.js:51:16)
    at HeaderParser.emit (node:events:394:28)
    at HeaderParser._finish (/Users/sujith/Documents/Personal_projects/VocabularyServer/node_modules/busboy/node_modules/dicer/lib/HeaderParser.js:68:8)
    at SBMH.<anonymous> (/Users/sujith/Documents/Personal_projects/VocabularyServer/node_modules/busboy/node_modules/dicer/lib/HeaderParser.js:40:12)

如果我从邮递员请求中删除文件,它可以调用uploadDP 函数。 我在这里做错了什么?

    标签: node.js express multer express-router


    【解决方案1】:

    最后,我让它工作了。这是我的解决方案,

    首先,我在我的主服务器文件中添加了以下行,

    app.use(multer().any()); 这将让我所有的中间件访问req.body

    现在,在我的上传控制器中,我可以从req.files 数组访问文件并使用fs 模块手动保存文件。

    这是上传控制器的最终代码,

    const fs = require("fs");
    const path = require("path");
    
    function isValidImageFile(file) {
      // Allowed ext
      let filetypes = /jpeg|jpg|png|gif|webp/;
      let extname = filetypes.test(path.extname(file.originalname).toLowerCase());
      let mimetype = filetypes.test(file.mimetype);
    
      if (mimetype && extname) return true;
      else false;
    }
    
    exports.uploadDP = async (req, res) => {
      var error = undefined;
      var files = req.files;
      if (files && files[0]) {
        const my_dp_file = files[0];
        var fileToSave = path.join(
          __dirname,
          "../user_uploads/images/dp/" +
            req.user._id +
            path.extname(my_dp_file.originalname)
        );
        if (isValidImageFile(my_dp_file)) {
          fs.writeFile(fileToSave, my_dp_file.buffer, function (err) {
            if (err) error = err;
            else res.send("file saved successfully");
          });
        } else error = "Not a valid image file";
      } else error = "No files found";
      if (error) {
        console.log(error);
        res.send(error);
      }
    };
    

    【讨论】:

      【解决方案2】:

      穆特官方docs

      警告:确保您始终处理用户上传的文件。永远不要将 multer 添加为全局中间件,因为恶意软件 用户可以将文件上传到您没有预料到的路线。仅有的 在您处理上传文件的路线上使用此功能。

      因此,我建议探索一种更安全的文件处理方式,如回答 here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-08-11
        • 2021-04-05
        • 2015-09-15
        • 1970-01-01
        • 2018-01-20
        • 2021-01-02
        • 1970-01-01
        相关资源
        最近更新 更多