如何通过单个Multer实例实现图片与视频差异化文件大小限制?
可以基于现有代码实现,无需创建多个Multer实例
完全不需要拆分Multer实例,只需在现有代码基础上补充全局大小限制和字段级大小验证逻辑即可实现需求。具体步骤如下:
实现思路
- 设置全局最大文件大小为视频的上限(100MB),避免超大文件占用不必要的带宽;
- 为每个上传字段定义对应的大小限制(图片类10MB,视频类100MB);
- 新增一个自定义中间件,在文件上传完成后检查每个文件的大小是否符合对应字段的规则;
- 处理Multer自带的全局大小超限错误。
修改后的完整代码
import path from "path"; import multer from "multer"; import { TEMP_DIRECTORY_PATH } from "../constants.js"; import { ApiError } from "../utils/ApiError.js"; const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, TEMP_DIRECTORY_PATH); }, filename: function (req, file, cb) { const fileName = Date.now() + "-" + Math.round(Math.random() * 1e9); const fileExtension = path.extname(file.originalname); cb(null, fileName + fileExtension); }, }); const imageMimeTypes = [ "image/png", "image/jpeg", "image/webp", "image/svg+xml", ]; const videoMimeTypes = ["video/mp4", "video/webm"]; const allowedMimeTypesForFields = { avatar: imageMimeTypes, coverImage: imageMimeTypes, videoFile: videoMimeTypes, thumbnail: imageMimeTypes, featuredImage: imageMimeTypes, }; // 定义各字段的大小限制(单位:字节) const fieldSizeLimits = { avatar: 10 * 1024 * 1024, // 10MB coverImage: 10 * 1024 * 1024, videoFile: 100 * 1024 * 1024, // 100MB thumbnail: 10 * 1024 * 1024, featuredImage: 10 * 1024 * 1024, }; const fileFilter = (req, file, cb) => { const allowedMimeTypesForField = allowedMimeTypesForFields[file.fieldname]; if (!allowedMimeTypesForField) { return cb( new ApiError( 500, `Invalid field ${file.fieldname}. Please ensure you are uploading to a valid field.` ), false ); } if (allowedMimeTypesForField.includes(file.mimetype)) { cb(null, true); } else { cb( new ApiError( 400, `Invalid file type for ${file.fieldname}. Allowed file types are ${allowedMimeTypesForField.map((type) => type.split("/")[1]).join(", ")}.` ), false ); } }; // 添加全局limits,限制最大文件为100MB(视频的上限) export const upload = multer({ storage, fileFilter, limits: { fileSize: 100 * 1024 * 1024 } }); // 自定义中间件:验证各字段的文件大小是否符合要求 export const validateFileSizes = (req, res, next) => { if (!req.files) return next(); for (const fieldName in req.files) { const files = req.files[fieldName]; const maxSize = fieldSizeLimits[fieldName]; for (const file of files) { if (file.size > maxSize) { return next(new ApiError( 400, `${fieldName} exceeds maximum allowed size of ${maxSize / (1024 * 1024)}MB. Uploaded file size: ${Math.round(file.size / (1024 * 1024))}MB` )); } } } next(); };
路由使用示例
// 示例上传路由 router.post('/media/upload', upload.fields([ { name: 'avatar', maxCount: 1 }, { name: 'videoFile', maxCount: 1 }, { name: 'coverImage', maxCount: 1 } ]), validateFileSizes, (req, res) => { // 处理上传后的业务逻辑 res.status(200).json({ message: 'Files uploaded successfully' }); } );
补充错误处理
添加全局错误处理中间件,捕获Multer自带的大小超限错误:
app.use((err, req, res, next) => { if (err instanceof multer.MulterError) { if (err.code === 'LIMIT_FILE_SIZE') { return res.status(400).json(new ApiError(400, 'File exceeds maximum allowed size of 100MB')); } return res.status(400).json(new ApiError(400, err.message)); } next(err); });
内容的提问来源于stack exchange,提问作者Bhomik Ranjan
相关产品推荐
相关产品推荐

