如何使用Multer验证上传文件的最小数量,少于指定值时返回错误
Multer 实现最小上传文件数量校验方案
Multer 本身仅内置了最大上传文件数的限制能力,要实现最少上传3个文件、且不足数量时不保存文件到服务器的要求,需要自行封装校验逻辑,注意不要在fileFilter钩子中判断文件总数,该钩子逐文件触发,执行时req.files还未完成赋值,无法拿到完整的文件列表统计数量。
实现思路
- 先通过内存存储模式的Multer解析所有上传文件,不会提前写入磁盘,避免产生无效临时文件
- 解析完成后先校验文件总数量,不足3个直接返回错误,丢弃内存中的文件数据
- 数量校验通过后,再将文件写入磁盘目标目录,生成自定义文件名
完整实现代码
const multer = require('multer'); const fs = require('fs'); const path = require('path'); // 配置磁盘写入规则,校验通过后调用 const saveFileToDisk = (file) => { const extension = file.originalname.slice(file.originalname.lastIndexOf('.')); const fileName = Date.now() + extension; const filePath = path.join('./public/files', fileName); // 写入磁盘 fs.writeFileSync(filePath, file.buffer); // 返回文件信息,挂载到req上 return { originalname: file.originalname, filename: fileName, path: filePath, size: file.size, mimetype: file.mimetype } } function uploadFile() { // 先用内存存储解析文件,不提前写入磁盘 const memoryStorage = multer.memoryStorage(); const upload = multer({ storage: memoryStorage, limits: {fileSize: 11657128, files: 3}, // 这里的files:3是限制最大3个,可根据需求调整 fileFilter: function(_req, file, cb) { // 这里可以做文件类型校验,比如只允许文本文件 const allowedMimeTypes = ['text/plain']; if (allowedMimeTypes.includes(file.mimetype)) { cb(null, true); } else { cb(new Error('不是文本类型文件'), false); } } }).array('file'); // 封装自定义中间件,加数量校验 return (req, res, next) => { upload(req, res, function (err) { if (err) { // 捕获multer的错误,比如文件超过大小、数量超过最大值等 return res.status(400).json({error: err.message}); } // 校验最小文件数量 if (!req.files || req.files.length < 3) { return res.status(400).json({error: '最少需要上传3个文件'}); } // 校验通过,将内存中的文件写入磁盘 try { const processedFiles = req.files.map(file => saveFileToDisk(file)); req.files = processedFiles; next(); } catch (writeErr) { return res.status(500).json({error: '文件保存失败'}); } }) } } module.exports = uploadFile;
调用方式
在路由中直接引入使用即可,和原调用逻辑完全兼容:
const uploadFile = require('./你保存配置的文件名'); app.post('/upload', uploadFile(), (req, res) => { // 到这里已经完成了数量校验和文件保存,req.files里是保存后的文件信息 res.json({msg: '上传成功', files: req.files}); })
原代码问题说明
你原有代码中的fileFilter逻辑是无效的,req.files在该钩子执行时还未被赋值,永远返回undefined,所以文件类型校验不会生效,上述代码已经修正了该问题,你可以根据需求调整允许的文件MIME类型。
内容的提问来源于stack exchange,提问作者MiriamS
相关产品推荐
相关产品推荐

