如何为Multer中间件设置动态文件大小限制?
解决Multer从数据库动态配置文件大小限制的问题
因为Multer初始化是同步操作,无法直接在limits.fileSize中使用异步函数的返回值,这里提供两种可行方案:
方案一:启动时预加载配置(适合配置不频繁变更的场景)
在应用启动阶段先获取文件大小限制,再初始化Multer实例,调整导出方式为异步导出:
const multer = require("multer"); const SettingModel = require("../../models/Setting"); const SequelizeService = require("../app/sequelize/sequelize.service"); let Setting = new SequelizeService(SettingModel); async function getSizeLimit() { let setting = await Setting.findOne({ raw: true }); return 1024 * 1024 * setting.sizeLimit; } const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, "./uploads/"); }, filename: function (req, file, cb) { cb(null, file.originalname.replace(/\s+/g, "")); }, }); const fileFilter = (req, file, cb) => { if ( file.mimetype === "image/jpeg" || file.mimetype === "image/png" || file.mimetype === "image/webp" ) { cb(null, true); } else { cb(new Error("Not an image! Please upload an image.", 400), false); } }; // 异步导出Multer实例 exports.getUploadMiddleware = async () => { const sizeLimit = await getSizeLimit(); return multer({ storage: storage, limits: { fileSize: sizeLimit, }, fileFilter: fileFilter, }); };
路由文件中需先获取中间件再使用:
const { getUploadMiddleware } = require("./path/to/your/multer-config"); // 初始化路由时调用 (async () => { const upload = await getUploadMiddleware(); app.post("/upload", upload.single("file"), (req, res) => { // 处理上传逻辑 }); })();
方案二:动态中间件(适合配置需要实时更新的场景)
每次请求时先从数据库获取最新的大小限制,再动态生成Multer实例处理请求:
const multer = require("multer"); const SettingModel = require("../../models/Setting"); const SequelizeService = require("../app/sequelize/sequelize.service"); let Setting = new SequelizeService(SettingModel); async function getSizeLimit() { let setting = await Setting.findOne({ raw: true }); return 1024 * 1024 * setting.sizeLimit; } const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, "./uploads/"); }, filename: function (req, file, cb) { cb(null, file.originalname.replace(/\s+/g, "")); }, }); const fileFilter = (req, file, cb) => { if ( file.mimetype === "image/jpeg" || file.mimetype === "image/png" || file.mimetype === "image/webp" ) { cb(null, true); } else { cb(new Error("Not an image! Please upload an image.", 400), false); } }; // 自定义动态中间件 exports.upload = async (req, res, next) => { try { const sizeLimit = await getSizeLimit(); // 根据需求替换为single/array/fields等方法 const uploadMiddleware = multer({ storage: storage, limits: { fileSize: sizeLimit, }, fileFilter: fileFilter, }).single("file"); uploadMiddleware(req, res, next); } catch (err) { next(err); } };
路由中直接使用该中间件:
const { upload } = require("./path/to/your/multer-config"); app.post("/upload", upload, (req, res) => { // 处理上传逻辑 });
方案对比
- 方案一:仅启动时查询一次数据库,性能更优,适合配置长期稳定的场景;若配置更新,需重启应用生效。
- 方案二:每次请求都获取最新配置,实时性强,但会增加数据库查询量,适合配置需要频繁变动的场景。
内容的提问来源于stack exchange,提问作者niloufar padkan
相关产品推荐
相关产品推荐

