【问题标题】:How to validate file extension with Multer middleware如何使用 Multer 中间件验证文件扩展名
【发布时间】:2020-06-10 00:15:40
【问题描述】:

我使用 Multer 上传文件或图像。问题是无法验证真实的文件扩展名。

示例:如果有人将filename.exe 重命名为filename.png,则上传仍然有效。

您能否建议我解决此问题的解决方案?谢谢

我是这样使用的,但需要验证文件的真实 ext

fileFilter: async function (req, file, callback) {
    var ext = path.extname(file.originalname);
    if(ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg' && ext !== '.zip') {
        return callback(new Error('Only images and zip are allowed'));
    }
    // I want next function to validate real ext of files here. 
    callback(null, true); 
  },

【问题讨论】:

    标签: node.js multer file-type


    【解决方案1】:

    从 Multer 2.x.x 开始您可以检查上传参数的扩展名和 MIME 类型。这是一个示例代码。

    const storage = multer.diskStorage({
        destination: './uploadedContent',
        filename: function(_req, file, cb){
          
          cb(null,file.fieldname + '-' + Date.now() + path.extname(file.originalname));
        } 
      });
    var upload = multer({
        storage: storage,
        limits: {
            fields: 5,
            fieldNameSize: 50, // TODO: Check if this size is enough
            fieldSize: 20000, //TODO: Check if this size is enough
            // TODO: Change this line after compression
            fileSize: 15000000, // 150 KB for a 1080x1080 JPG 90
        },
        fileFilter: function(_req, file, cb){
            checkFileType(file, cb);
        }
    }).single('postPicture');
    function checkFileType(file, cb){
      // Allowed ext
      const filetypes = /jpeg|jpg|png|gif/;
      // Check ext
      const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
      // Check mime
      const mimetype = filetypes.test(file.mimetype);
    
      if(mimetype && extname){
        return cb(null,true);
      } else {
        cb('Error: Images Only!');
      }
    }
    

    不要忘记检查您的文件权限。您不希望以某种方式执行上传的文件。 遗憾的是,最新的 npm 版本是 1.4.3,其中 Multer mime 类型基于来自客户端的 type 属性。至少在 windows 中,该属性取决于文件扩展名,而不是文件内容。

    【讨论】:

    • 您只能使用 Multer 2.x.x 版本执行此操作,但当前可用的 npm 版本 1.4.3 仅依赖于标题中有关文件类型的内容。并且是基于大多数系统中的文件扩展名。因此,目前检查 mimetype 不会帮助您进行验证。你必须使用文件类型来做到这一点
    【解决方案2】:

    有两个步骤:

    1. fileFilter 选项上 multer 提供的 mime 类型过滤
    2. 使用file-type从文件缓冲区/流中过滤真正的mime类型。

    定义白名单 mime 类型:

    const whitelist = [
      'image/png',
      'image/jpeg',
      'image/jpg',
      'image/webp'
    ]
    

    第一步示例:

    const upload = multer({
      storage: multer.diskStorage({
        destination: 'public/uploads/',
        filename: (req, file, cb) => {
          const name = slugify(file.originalname, { lower: true })
          cb(null, `${new Date().getTime()}-${name}`)
        },
      }),
      fileFilter: (req, file, cb) => {
        if (!whitelist.includes(file.mimetype)) {
          return cb(new Error('file is not allowed'))
        }
    
        cb(null, true)
      }
    })
    

    第二步示例:

    const FileType = require('file-type')
    
    // ....
    // first step
    // ....
    
    /**
     * Second step
     */
    app.use('store', upload.single('image'), async (req, res, next) => {
      const meta = await FileType.fromFile(req.file.path)
    
      if (!whitelist.includes(meta.mime)) {
        return next(new Error('file is not allowed'))
      }
    
      res.json({
        file: req.file,
        body: req.body,
      })
    })
    

    我尝试重命名 document.pdf -> document.png,它通过了第一次检查,但在第二次检查中被抓住了。

    【讨论】:

    • 这是最好的答案,因为两步过程提供了最大的安全性。顺便说一句,无法在 fileFilter 函数中检查 FileType,因为在该步骤中文件(或缓冲区)尚不可用。
    【解决方案3】:

    基本上你需要的是可以用原始文件类型验证扩展名的东西。

    从博客复制

        var upload = multer({
      storage: storage,
      fileFilter: (req, file, cb) => {
        if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") {
          cb(null, true);
        } else {
          cb(null, false);
          return cb(new Error('Only .png, .jpg and .jpeg format allowed!'));
        }
      }
    });
    

    Blog Link

    如果这对您不起作用,请考虑使用单独的模块从缓冲区数据中验证文件类型。

    【讨论】:

      猜你喜欢
      • 2019-02-04
      • 2015-10-14
      • 2018-11-26
      • 1970-01-01
      • 2017-06-27
      • 1970-01-01
      • 1970-01-01
      • 2013-09-03
      • 2011-04-07
      相关资源
      最近更新 更多