You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Multer fileFilter校验扩展名报错时不合规文件仍被保存问题

Multer文件过滤后非法文件仍被存储问题修复

预期功能

配置Express的Multer中间件,仅允许保存扩展名为pdf的上传文件,非pdf格式文件返回错误提示且不予存储。

问题现象

上传jpg等非pdf格式文件时,接口可正确返回预期的please upload PDF file extension错误响应,但不符合格式要求的文件依然被存入指定的images目录,与预期逻辑不符。

问题复现代码

const express = require("express");
const app = new express();
const multer = require("multer");
const upload = multer({
  dest: "images", // 文件存储目录
  limits: 100000, // 原代码此处写法有误,限制文件大小需传入对象指定fileSize字段
  fileFilter(req, file, cb) {
    if (!file.originalname.endsWith("pdf")) {
      cb(new Error("please upload PDF file extension"));
      // 此处缺少return终止逻辑,后续代码仍会执行
    }
    cb(undefined, true);
  },
});
app.post("/upload", upload.single("upload"), (req, res) => {
  res.send();
});
app.listen(8000, () => {
  console.log("server fired off");
});

故障原因

fileFilter方法存在执行流漏洞:判断到非pdf文件触发错误回调后,没有终止函数执行,后续的cb(undefined, true)会照常运行,相当于同时向Multer传递了「文件非法」和「文件允许通过」两个矛盾指令,最终导致错误正常返回,但文件依然被写入存储目录。
另外原代码的limits配置写法错误,直接传入数字不会生效,需要传入对象通过fileSize字段指定大小限制;原后缀判断逻辑也存在漏洞,endsWith("pdf")会把xxxpdf这类无后缀的文件误判为合法pdf,且不支持大写.PDF后缀校验。

修复后代码

const express = require("express");
const app = new express();
const multer = require("multer");
const upload = multer({
  dest: "images",
  limits: {
    fileSize: 100000 // 正确配置1MB大小限制
  },
  fileFilter(req, file, cb) {
    // 用正则匹配.pdf后缀,兼容大写格式,同时校验后缀前的点避免误判无后缀文件
    if (!/\.pdf$/i.test(file.originalname)) {
      // 错误回调后加return,阻断后续逻辑执行
      return cb(new Error("please upload PDF file extension"));
    }
    cb(undefined, true);
  },
});
// 增加专属错误处理中间件,统一捕获上传阶段的错误
app.post("/upload", upload.single("upload"), (req, res) => {
  res.send();
}, (error, req, res, next) => {
  res.status(400).send({ error: error.message });
});
app.listen(8000, () => {
  console.log("server fired off");
});

内容的提问来源于stack exchange,提问作者mahir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 04:12:22