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

如何在Multer中为多字段设置不同的文件大小限制?

解决Multer分字段设置文件大小限制的问题

核心问题

Multer的limits配置是全局生效的,没法给images和video这类不同字段单独设置大小限制;而fileFilter回调触发时文件还没接收完成,拿不到准确的file.size,导致提前校验大小的逻辑完全失效。

简洁解决方案

不用拆分多个upload处理器,只需要先把全局limits设为所有字段里的最大允许值(这里是视频的100MB),再在文件上传完成后的路由处理逻辑里,针对不同字段的文件分别做大小校验即可。

修改后的完整代码

const fs = require('fs');
const uuidv4 = require('uuid').v4;
const multer = require('multer');

const DIR = './uploads/';
const MAX_IMAGE_SIZE = 2 * 1024 * 1024; // 2MB
const MAX_VIDEO_SIZE = 100 * 1024 * 1024; // 100MB

const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        fs.mkdirSync(DIR, { recursive: true });
        cb(null, DIR);
    },
    filename: (req, file, cb) => {
        const fileName = file.originalname.toLowerCase().split(' ').join('-');
        cb(null, uuidv4() + '-' + fileName)
    }
});

// 全局limits设为最大允许值,避免合法大文件被提前拦截
const upload = multer({
    storage: storage,
    limits: { fileSize: MAX_VIDEO_SIZE },
    fileFilter: (req, file, cb) => {
        // fileFilter里只做格式校验,大小校验放到路由处理阶段
        if (file.fieldname === "images") {
            const allowedImageTypes = ["image/png", "image/jpg", "image/jpeg", "image/webp"];
            if (allowedImageTypes.includes(file.mimetype)) {
                cb(null, true);
            } else {
                req.imageValidationError = "不支持的图片格式";
                cb(null, false); // 传false而非抛错,避免中断整个上传流程
            }
        } else if (file.fieldname === "video") {
            const allowedVideoTypes = ["video/ogg", "video/webm", "video/mp4", "video/ogv"];
            if (allowedVideoTypes.includes(file.mimetype)) {
                cb(null, true);
            } else {
                req.videoValidationError = "不支持的视频格式";
                cb(null, false);
            }
        } else {
            cb(new Error("未知的文件字段"));
        }
    }
});

// 示例路由处理
app.post('/upload', upload.fields([
    { name: 'images', maxCount: 10 }, // 按需设置图片最大上传数量
    { name: 'video', maxCount: 1 }
]), (req, res) => {
    const validationErrors = [];

    // 校验图片大小
    if (req.files?.images) {
        req.files.images.forEach(image => {
            if (image.size > MAX_IMAGE_SIZE) {
                validationErrors.push(`图片 ${image.originalname} 大小超过2MB限制`);
                // 可选:删除已上传的违规文件
                fs.unlinkSync(image.path);
            }
        });
    }

    // 校验视频大小
    if (req.files?.video) {
        const video = req.files.video[0];
        if (video.size > MAX_VIDEO_SIZE) {
            validationErrors.push(`视频 ${video.originalname} 大小超过100MB限制`);
            fs.unlinkSync(video.path);
        }
    }

    // 收集格式校验的错误
    if (req.imageValidationError) validationErrors.push(req.imageValidationError);
    if (req.videoValidationError) validationErrors.push(req.videoValidationError);

    if (validationErrors.length) {
        return res.status(400).json({ errors: validationErrors });
    }

    // 后续业务逻辑
    res.status(200).json({ message: "文件上传成功", files: req.files });
});

方案说明

  1. 全局limits兜底:把limits.fileSize设为最大允许值,确保合法的大文件不会被Multer提前拦截。
  2. 分阶段校验:fileFilter只处理格式合法性,大小校验放到上传完成后,此时file.size是准确值。
  3. 错误统一处理:把格式错误存在req对象中,和大小错误一起在路由里统一收集返回,避免中途中断上传。
  4. 可选清理:对违规文件执行删除操作,避免服务器存储无效文件。

内容的提问来源于stack exchange,提问作者M.KH

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 14:06:39