MongoDB GridFS报grid.mongo.ObjectID is not a constructor错误咨询
错误原因
- 你使用的
gridfs-stream包与Mongoose 6.x及以上版本不兼容:Mongoose 6开始将原mongoose.mongo.ObjectID(末尾大写D)重命名为mongoose.mongo.ObjectId(末尾小写d),但gridfs-stream内部仍然在调用大写D的ObjectID构造函数,因此触发类型错误。 - 额外说明:
gridfs-stream包已经多年未更新,本身不兼容新版MongoDB/Mongoose生态。
修复方案
方案1:快速兼容修复(无需更换依赖)
在初始化GridFS实例后,手动给grid.mongo.ObjectID赋值指向正确的构造函数即可,修改你的creatConnectionGridFs方法:
private creatConnectionGridFs(): void { const connection = mongoose.createConnection(`${process.env.MONGODB}`); connection.once('open', () => { this.gridFs = Grid(connection.db, mongoose.mongo); // 新增下面这行手动映射兼容 this.gridFs.mongo.ObjectID = mongoose.mongo.ObjectId; this.gridFs.collection('uploads'); }); }
修改后原有调用createReadStream的代码不需要变动,即可正常运行。
方案2:使用原生GridFSBucket(更稳定,推荐)
新版MongoDB Node驱动已经内置了GridFS操作能力,不需要额外依赖第三方gridfs-stream包,可直接替换实现:
首先删除gridfs-stream相关依赖和类型定义,修改代码如下:
import { GridFSBucket } from 'mongodb'; export default class UploadController { private gridFsBucket: GridFSBucket; constructor() { autoBine(this); this.creatConnectionGridFs(); } getImageByName(req: Request, res: Response, next: NextFunction) { from(this.gridFsBucket.find({ filename: req.params.filename }).toArray()) .pipe( switchMap((files) => { if (files.length) { return of(files[0]); } return throwError(() => new createError.NotFound()); }) ) .subscribe({ next: (file) => { try { const readstream = this.gridFsBucket.openDownloadStreamByName(file.filename); readstream.pipe(res); } catch (error) { console.log(error); res.json(null); } }, error: (err) => { handleRouteErrors(err, res, next); }, }); } private creatConnectionGridFs(): void { const connection = mongoose.createConnection(`${process.env.MONGODB}`); connection.once('open', () => { // 初始化原生GridFSBucket,指定集合名为uploads this.gridFsBucket = new GridFSBucket(connection.db, { bucketName: 'uploads' }); }); } }
该方案无第三方依赖兼容问题,长期维护性更好。
内容的提问来源于stack exchange,提问作者Miguel Frias
相关产品推荐
相关产品推荐

