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

使用Multer(upload.any())无法向客户端返回非法文件类型错误

解决Multer fileFilter无法触发错误处理的问题

要实现文件类型不合法时触发错误并返回指定响应,你需要调整fileFilter的回调方式,并在错误处理逻辑中区分自定义错误类型:

修改步骤:

  1. 调整fileFilter的错误触发方式:
    不再使用cb(null, false)跳过文件,而是通过cb(new Error())主动抛出错误,错误信息明确说明文件类型问题。

  2. 优化错误处理逻辑:
    在multer的回调错误处理中,判断错误信息,返回400状态码(客户端错误)而非500(服务器错误),同时返回自定义的错误提示。

修改后的完整代码:

const multer = require('multer');
const storage = multer.memoryStorage();
const crypto = require('crypto');
const sharp = require('sharp');
const { AwsUploadFile } = require('../../utils/s3');

const generateFileName = (mimeType, bytes = 32) => {
  const extension = mimeType.split('/')[1]; // Extracts file extension from MIME type
  return crypto.randomBytes(bytes).toString('hex') + '.' + extension;
};

const fileFilter = (req, file, cb) => {
  if (
    file.mimetype.startsWith('image/') ||
    file.mimetype.startsWith('video/')
  ) {
    cb(null, true);
  } else {
    // 抛出自定义错误,触发错误处理块
    cb(new Error('仅支持图片和视频类型的文件'));
  }
};

const upload = multer({
  storage: storage,
  limits: { fileSize: 50 * 1024 * 1024 }, // 50MB limit
  fileFilter: fileFilter,
});

async function fileUpload(req, res, next) {
  const multerUpload = upload.any();
  multerUpload(req, res, async (err) => {
    if (err instanceof multer.MulterError) {
      return res.status(500).json({
        success: false,
        message: '文件上传错误',
        error: err.message,
      });
    } else if (err) {
      // 判断是否为文件类型错误,返回400客户端错误
      if (err.message === '仅支持图片和视频类型的文件') {
        return res.status(400).json({
          success: false,
          message: '文件类型不合法',
          error: err.message,
        });
      }
      // 其他未知错误
      console.log('通用错误:', err.message);
      return res.status(500).json({
        success: false,
        message: '处理过程中发生错误',
        error: err.message,
      });
    }

    if (!req.files || req.files.length === 0) {
      return res.status(400).json({
        success: false,
        message: '未上传任何文件',
      });
    }

    const file = req.files[0];
    const getFileName = generateFileName(file.mimetype);
    file.originalname = file.mimetype.startsWith('video/')
      ? 'public/videos/' + getFileName
      : 'public/images/' + getFileName;

    if (file.mimetype.startsWith('image/')) {
      try {
        const fileBuffer = await sharp(file.buffer)
          .resize({ height: 1920, width: 1080, fit: 'contain' })
          .toBuffer();

        file.buffer = fileBuffer;
      } catch (sharpError) {
        return res.status(500).json({
          success: false,
          message: '图片处理错误',
          error: sharpError.message,
        });
      }
    }

    try {
      const { fileLink, result } = await AwsUploadFile({
        fileBuffer: file.buffer,
        fileName: file.originalname,
        mimeType: file.mimetype,
      });

      req.fileUrl = fileLink;
      req.fileType = file.mimetype.split('/')[0];
      next();
    } catch (awsError) {
      return res.status(500).json({
        success: false,
        message: '上传至AWS失败',
        error: awsError.message,
      });
    }
  });
}

module.exports = fileUpload;

关键说明:

  • fileFilter中使用cb(new Error('xxx'))会直接触发multer回调的错误分支,替代原来的跳过逻辑。
  • 在错误处理中通过判断错误信息,将文件类型错误归类为客户端错误(400状态码),更符合HTTP语义,同时返回清晰的提示信息给客户端。
  • 保留了对Multer内置错误(如文件大小超限)和其他未知错误的区分处理,保证逻辑完整性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 15:01:18