使用Multer与multer-gridFs-storage上传图片至MongoDB时遇TypeError错误
解决Multer + multer-gridFs-storage上传MongoDB时的
TypeError: Cannot read property 'readPreference' of undefined错误 这个错误我之前帮朋友排查过,核心原因是GridStore实例化时没有拿到有效的MongoDB数据库实例(db对象为undefined),通常和版本兼容性或者数据库连接配置不当有关,下面给你一步步的解决方案:
1. 先排查版本兼容性问题
这个错误大概率出现在你使用了MongoDB驱动4.x+版本的情况下——因为从MongoDB 4.x开始,GridStore已经被官方弃用,改用GridFSBucket了,但旧版的multer-gridFs-storage可能还在依赖GridStore,导致调用时找不到正确的db属性。
解决思路二选一:
- 降级MongoDB驱动:把
mongodb包版本降到3.7.x左右(这个版本是兼容旧版multer-gridFs-storage的稳定版),执行命令:npm install mongodb@3.7.4 --save - 升级并改用GridFSBucket:如果不想降级驱动,就需要调整代码使用
GridFSBucket替代GridStore,同时确保multer-gridFs-storage是最新版本(部分新版已经支持GridFSBucket)。
2. 修正数据库连接与存储配置
不管用哪种版本,都要确保数据库连接成功后再初始化存储配置,避免db对象未就绪:
方案一:兼容旧版驱动(mongodb 3.x)+ multer-gridFs-storage
const mongoose = require('mongoose'); const Grid = require('gridfs-stream'); const multer = require('multer'); const GridFsStorage = require('multer-gridfs-storage'); // 先建立数据库连接 mongoose.connect('mongodb://localhost:27017/yourDB', { useNewUrlParser: true, useUnifiedTopology: true }); const conn = mongoose.connection; // 连接成功后初始化GridFS let gfs; conn.once('open', () => { gfs = Grid(conn.db, mongoose.mongo); gfs.collection('uploads'); // 指定存储文件的集合名 }); // 配置multer的storage const storage = new GridFsStorage({ url: 'mongodb://localhost:27017/yourDB', file: (req, file) => { return new Promise((resolve, reject) => { const fileInfo = { filename: file.originalname, bucketName: 'uploads' // 和上面的集合名保持一致 }; resolve(fileInfo); }); } }); const upload = multer({ storage });
方案二:新版驱动(mongodb 4.x+)+ GridFSBucket
如果坚持用新版驱动,建议直接基于GridFSBucket实现上传逻辑,避免依赖旧版的multer-gridFs-storage:
const { MongoClient, GridFSBucket } = require('mongodb'); const multer = require('multer'); const fs = require('fs'); const url = 'mongodb://localhost:27017/yourDB'; let bucket; // 先连接数据库并初始化GridFSBucket MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true }) .then(client => { const db = client.db('yourDB'); bucket = new GridFSBucket(db, { bucketName: 'uploads' }); }) .catch(err => console.error('数据库连接失败:', err)); // 用multer先接收文件,再通过GridFSBucket写入 const upload = multer({ dest: './temp/' }); // 先临时存储到本地 // 处理上传的路由 app.post('/upload', upload.single('file'), (req, res) => { if (!bucket) return res.status(500).send('GridFS未初始化'); // 把临时文件流写入GridFS const uploadStream = bucket.openUploadStream(req.file.originalname); const readStream = fs.createReadStream(req.file.path); readStream.pipe(uploadStream); uploadStream.on('finish', () => { // 删除临时文件 fs.unlinkSync(req.file.path); res.send('文件上传成功'); }); });
3. 额外排查点
- 确保你的数据库连接字符串正确,没有拼写错误,MongoDB服务正在运行;
- 检查
bucketName是否一致,集合名写错也可能导致类似问题; - 不要在数据库连接完成前就创建
storage实例,否则db对象还未就绪会变成undefined。
内容的提问来源于stack exchange,提问作者karthik_varma_k
相关产品推荐
相关产品推荐

