Node.js Multer按文件类型设置文件大小限制方法咨询
按文件类型设置Multer差异化大小限制的实现方案
嘿,这个需求我之前刚搞定过!Multer默认的limits.fileSize是全局统一的,但我们可以通过自定义文件过滤器+监听文件流的方式,轻松实现按文件类型差异化设置大小限制,甚至还能提前中止超大文件的上传,避免浪费服务器带宽和存储资源。
实现思路
- 先定义好不同文件类型的规则(正则匹配+对应大小限制),方便后续维护
- 在自定义
fileFilter里,先判断文件所属类型,拿到对应的大小限制 - 监听文件上传流,实时计算已上传的字节数,一旦超过对应类型的限制,立即中止上传并返回明确错误
- 同时设置全局最大限制(取所有类型中最大的那个值),作为第一道防线
完整代码示例
首先,我们先定义各个文件类型的规则:
// 定义不同类型文件的大小限制(单位:字节) const fileSizeRules = { image: { // 匹配扩展名或MIME类型 match: /jpeg|jpg|png|gif/i, maxSize: 4 * 1024 * 1024 // 4MB }, video: { match: /mp4|avi/i, maxSize: 10 * 1024 * 1024 // 10MB }, audio: { match: /mp3|flac|wav|m4a/i, maxSize: 1 * 1024 * 1024 // 1MB } };
接下来配置Multer的存储和自定义文件过滤器:
const multer = require('multer'); const path = require('path'); // 配置磁盘存储 const storage = multer.diskStorage({ destination: (req, file, cb) => { // 替换成你的实际上传目录 cb(null, path.join(__dirname, 'uploads')); }, filename: (req, file, cb) => { // 生成唯一文件名,避免重复 const uniqueName = `${Date.now()}-${file.originalname}`; cb(null, uniqueName); } }); // 自定义文件过滤器,实现差异化大小限制 const customFileFilter = (req, file, cb) => { // 1. 判断文件所属类型 let targetRule = null; // 从扩展名和MIME类型两个维度匹配,提升准确性 const fileExt = file.originalname.split('.').pop().toLowerCase(); const mimeType = file.mimetype.toLowerCase(); Object.values(fileSizeRules).forEach(rule => { if (rule.match.test(fileExt) || rule.match.test(mimeType)) { targetRule = rule; } }); if (!targetRule) { return cb(new Error('不支持该文件类型,请上传图片、视频或音频文件'), false); } // 2. 监听文件流,实时检查大小 let uploadedBytes = 0; const maxAllowedBytes = targetRule.maxSize; file.stream.on('data', (chunk) => { uploadedBytes += chunk.length; // 如果已上传大小超过限制,立即中止上传 if (uploadedBytes > maxAllowedBytes) { file.stream.destroy(); // 终止文件流 const maxSizeMB = maxAllowedBytes / (1024 * 1024); cb(new Error(`文件大小超过限制:该类型文件最大允许${maxSizeMB}MB`), false); } }); // 3. 符合条件,允许上传 cb(null, true); }; // 初始化Multer实例,设置全局最大限制(取所有类型中的最大值) const upload = multer({ storage: storage, fileFilter: customFileFilter, limits: { fileSize: 10 * 1024 * 1024 // 全局最大10MB,和视频的限制一致 } });
最后在路由中使用,并添加错误处理:
const express = require('express'); const app = express(); // 单文件上传接口 app.post('/upload', upload.single('file'), (req, res) => { res.status(200).json({ message: '文件上传成功', fileInfo: { name: req.file.filename, size: req.file.size, type: req.file.mimetype } }); }); // 全局错误处理中间件,捕获Multer相关错误 app.use((err, req, res, next) => { // 处理Multer自带的错误(比如全局大小限制触发) if (err instanceof multer.MulterError) { if (err.code === 'LIMIT_FILE_SIZE') { return res.status(400).json({ error: '文件大小超过全局最大限制(10MB)' }); } return res.status(400).json({ error: err.message }); } // 处理我们自定义的错误 if (err.message) { return res.status(400).json({ error: err.message }); } // 其他未知错误 next(err); }); app.listen(3000, () => { console.log('服务器运行在http://localhost:3000'); });
注意事项
- 双重类型校验:同时检查文件扩展名和MIME类型,避免恶意文件绕过校验
- 权限设置:确保上传目录
uploads有正确的读写权限,否则会导致上传失败 - 错误提示:返回明确的错误信息,方便前端用户理解问题所在
- 资源清理:如果上传中途被中止,Multer不会自动删除已上传的部分文件,你可以在错误处理中添加逻辑清理这些临时文件(可选)
内容的提问来源于stack exchange,提问作者Lukas Morinyo




