当我在 multer 中使用文件过滤器时如何捕捉错误?

Posted

技术标签:

【中文标题】当我在 multer 中使用文件过滤器时如何捕捉错误?【英文标题】:How to catch the error when i am using file filter in multer? 【发布时间】:2018-05-20 06:57:06 【问题描述】:

我已经搜索过,但我找不到确切的解决方案。当我上传图像时,它应该只允许 jpg、jpeg、gif、png。如果有任何其他文件,它应该在 UI 中显示消息。我使用了以下代码

var upload = multer( storage: storage,
 fileFilter: function (req, file, cb) 
        var ext = path.extname(file.originalname);
        if(ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg') 
             return cb(new Error('Wrong extension type'));
            // if(Error)
            //     console.log("error file type")
            // 

        
        cb(null, true)
    

);

如果我尝试上传图片而不是 jpeg、jpg、png、git 它显示错误..但是如何在我的应用程序页面本身中显示为消息

Error: Wrong extension type
    at fileFilter (D:\Vishnu\octopus new\app\routes.js:912:24)
    at wrappedFileFilter (D:\Vishnu\octopus new\node_modules\multer\index.js:44:7)
    at Busboy.<anonymous> (D:\Vishnu\octopus new\node_modules\multer\lib\make-middleware.js:114:7)
    at emitMany (events.js:127:13)
    at Busboy.emit (events.js:201:7)
    at Busboy.emit (D:\Vishnu\octopus new\node_modules\busboy\lib\main.js:38:33)
    at PartStream.<anonymous> (D:\Vishnu\octopus new\node_modules\busboy\lib\types\multipart.js:213:13)
    at emitOne (events.js:96:13)
    at PartStream.emit (events.js:188:7)
    at HeaderParser.<anonymous> (D:\Vishnu\octopus new\node_modules\dicer\lib\Dicer.js:51:16)
    at emitOne (events.js:96:13)
    at HeaderParser.emit (events.js:188:7)
    at HeaderParser._finish (D:\Vishnu\octopus new\node_modules\dicer\lib\HeaderParser.js:68:8)
    at SBMH.<anonymous> (D:\Vishnu\octopus new\node_modules\dicer\lib\HeaderParser.js:40:12)
    at emitMany (events.js:127:13)
    at SBMH.emit (events.js:201:7)

请在这个问题上帮助我.. 提前致谢

【问题讨论】:

【参考方案1】:

我也一直在努力解决这个问题。我以为我找到了一个解决方案,但它最终对我来说效果不佳,但经过足够的修补和今晚环顾四周后,我找到了一个适合我的答案。我希望这有帮助。 我实际上是在四处寻找答案时发现了这个问题

所以我所做的是在您的示例中创建 req.fileValidationError

var upload = multer( 
     fileFilter: function (req, file, cb) 
          let ext = path.extname(file.originalname);
          if (ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg') 
               req.fileValidationError = "Forbidden extension";
               return cb(null, false, req.fileValidationError);
         
         cb(null, true);
     
);

然后在您的路线中,您要使用 if 语句检查 req.fileValidationError。如果它存在,那么你就知道有一个被禁止的扩展。

假设您在 app 变量下使用 express,并且您希望发送单个图像,它看起来像这样:

app.post('/your-upload-route', upload.single("your-input-name-here"), function(req, res) 
     if (req.fileValidationError) 
          // return res.sendFile();
          // or return res.end();
          // or even res.render(); whatever response you want here.
     
);

我希望这会有所帮助!如果其他人有不同的做法,我很乐意更新我的答案并了解其他人的见解。

【讨论】:

【参考方案2】:

添加到这个答案,顺便说一句,这就像一个魅力。

如果您想全面了解由 MIME 类型不接受的文件或未附加文件导致的错误,您可以执行以下操作:

将您的 FileFilter 函数设置为如下所示:

const upload = multer(
storage: //storage declaration here,
fileFilter: (req, file, cb) => 
        if (
            !file.mimetype.includes("image/png") &&
            !file.mimetype.includes("image/jpeg")
        ) 
            return cb(null, false);
        
        cb(null, true);
    
);

然后在您的路线或您的 req, res 范围内的任何地方,您可以通过检查通常保存上传文件信息的 req.file 变量来捕获错误并做出相应的响应:

if (!req.file) 
            console.log("No file received or invalid file type");
            return res.status(400).send(
                message: "No file received or invalid file type",
                success: false
            );

无需设置新的req 变量来保存ValidationError,如果用户未提供有效文件,您可以优雅地响应用户。

这是有效的,因为 FileFilter 将成功过滤掉与您的验证不匹配的文件,即使没有在回调中引发错误,但不会引发错误,它只是不会继续接受文件。我不完全理解为什么 multer 中的回调是以这种方式构建的,因为抛出错误的方法不会冒泡到您的路由或控制器。

但是,使用上面的代码,如果 fileFilter 完成了它的工作,当您使用 if(!req.file) 检查 req.file 是否存在(或在这种情况下不存在)时,您可以捕获无文件提交和验证失败一次没有从 fileFilter 的回调中抛出的混乱错误:)

【讨论】:

【参考方案3】:

fileFilter 回调应该是:

var upload = multer( 
    storage: storage,
    fileFilter: function (req, file, cb) 
        var ext = path.extname(file.originalname);
        if(ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg') 
            cb(new Error('Wrong extension type'), false);
        
        cb(null, true)
    
);

请求中的错误处理:

使用MulterError访问multer错误
const multer = require("multer");

router.post('/upload', function(req, res) 
    upload.single('field name')(req, res, function(err) 

        // FILE SIZE ERROR
        if (err instanceof multer.MulterError) 
            return res.end("Max file size 2MB allowed!");
        

        // INVALID FILE TYPE, message will return from fileFilter callback
        else if (err) 
            return res.end(err.message);
        

        // FILE NOT SELECTED
        else if (!req.file) 
            return res.end("File is required!");
        
 
        // SUCCESS
        else 
            console.log("File uploaded successfully!");
            console.log("File response", req.file);
        

    )
)

【讨论】:

【参考方案4】:

借助中间件处理异常的另一种方法

router.post("/v1/user/create",uploadFile,customBadRequestException,customBadFileRequestException)

自定义例外

exports.customBadRequestException = (req,res,next) => 
  if(!req.body || !req.body.data || !req.body.data.length || !req.file || !req.file.filename)
    return res.status(400).send( message: "Bad request" );
  
  next();
;

exports.customBadFileRequestException = (req,res,next) => 
  if (! /\.(jpe?g|png|gif|bmp)$/i.test(req.file.filename)) 
    return res.status(400).send( message: "Please upload only images" );
   
  next();
;

Multer 配置

const multer = require("multer");
    var storage = multer.diskStorage(
      destination: (req, file, cb) => 
        cb(null,"/Users/path/Desktop/testFiles");
      ,
      filename: (req, file, cb) => 
        cb(null, `$Date.now()-$file.originalname`);
      ,
    );
    
    var uploadFile = multer( storage: storage).single("file");
    module.exports = uploadFile;

【讨论】:

以上是关于当我在 multer 中使用文件过滤器时如何捕捉错误?的主要内容,如果未能解决你的问题,请参考以下文章

如何在multer中检查文件类型

如果未使用 multer 在 nodejs 中选择文件,则不更新

如何使用 multer 模块将图像上传到 mongodb

Multer 使用数据创建新文件夹

MongoDB & Multer - 如何将缓冲区二进制文件转换为图像?

使用multer上传时如何限制文件大小?