使用gridfs-stream上传图片报错:grid.mongo.ObjectID不是构造函数
Hey there! Let's break down this error you're facing when using gridfs-stream to upload images. That grid.mongo.ObjectID is not a constructor message almost always boils down to one of two issues: a version mismatch between gridfs-stream and your MongoDB driver, or an incorrect way of referencing the ObjectID constructor.
Common Causes & Solutions
1. Version Compatibility Issue
The gridfs-stream package hasn't been updated in years, and it doesn't play nicely with newer MongoDB drivers (version 4.x and above). Newer drivers changed how ObjectID is exported, which breaks gridfs-stream's internal references.
Quick fix:
- If you want to stick with gridfs-stream, downgrade your MongoDB driver to version 3.x. Run this command in your project:
npm install mongodb@3.7.3 - Alternatively, switch to MongoDB's official
GridFSBucket(recommended, since it's actively maintained and supports modern driver versions). I'll show an example of this below.
2. Fix ObjectID Reference (If Sticking with gridfs-stream)
If you don't want to downgrade the driver, you can explicitly import ObjectID from the MongoDB driver instead of using grid.mongo.ObjectID.
Here's how to adjust your code:
const router = require('express').Router(); const { MongoClient, ObjectId } = require('mongodb'); // Import ObjectId directly const Grid = require('gridfs-stream'); const database = require('../config/database'); // Your DB config // Initialize gridfs-stream correctly let gfs; MongoClient.connect(database.url, { useNewUrlParser: true, useUnifiedTopology: true }, (err, client) => { if (err) throw err; const db = client.db(database.name); Grid.mongo = db.mongo; // Bind the mongo instance gfs = Grid(db); }); // Your upload route example router.post('/upload', (req, res) => { // Use the imported ObjectId instead of grid.mongo.ObjectID const writestream = gfs.createWriteStream({ _id: new ObjectId(), filename: req.file.originalname, content_type: req.file.mimetype }); // Pipe the file to the writestream req.pipe(writestream); writestream.on('close', (file) => { res.json({ message: 'File uploaded', fileId: file._id }); }); writestream.on('error', (err) => { res.status(500).json({ error: err.message }); }); });
3. Migrate to Official GridFSBucket (Recommended)
Since gridfs-stream is unmaintained, using MongoDB's native GridFSBucket is a better long-term solution. Here's a quick example of how to implement the upload with it:
const router = require('express').Router(); const { MongoClient, GridFSBucket } = require('mongodb'); const database = require('../config/database'); const multer = require('multer'); // Assuming you're using multer for file uploads const upload = multer({ storage: multer.memoryStorage() }); let bucket; MongoClient.connect(database.url, { useNewUrlParser: true, useUnifiedTopology: true }, (err, client) => { if (err) throw err; const db = client.db(database.name); bucket = new GridFSBucket(db); }); router.post('/upload', upload.single('image'), (req, res) => { if (!req.file) { return res.status(400).json({ error: 'No file uploaded' }); } const uploadStream = bucket.openUploadStream(req.file.originalname, { contentType: req.file.mimetype }); uploadStream.end(req.file.buffer); uploadStream.on('finish', () => { res.json({ message: 'File uploaded', fileId: uploadStream.id }); }); uploadStream.on('error', (err) => { res.status(500).json({ error: err.message }); }); });
This approach avoids the compatibility issues entirely and uses MongoDB's officially supported API.
内容的提问来源于stack exchange,提问作者geolaw

