如何在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 }); });
方案说明
- 全局limits兜底:把
limits.fileSize设为最大允许值,确保合法的大文件不会被Multer提前拦截。 - 分阶段校验:
fileFilter只处理格式合法性,大小校验放到上传完成后,此时file.size是准确值。 - 错误统一处理:把格式错误存在
req对象中,和大小错误一起在路由里统一收集返回,避免中途中断上传。 - 可选清理:对违规文件执行删除操作,避免服务器存储无效文件。
内容的提问来源于stack exchange,提问作者M.KH
相关产品推荐
相关产品推荐

