Node.js结合Monk将图片存储至MongoDB的实现方法及示例请求
Absolutely, you can store images in MongoDB using Monk with GridFS—no Mongoose required! Let’s walk through a complete, working example step by step, using Multer for handling file uploads and GridFS for managing binary data storage.
First, make sure you have these packages installed in your Node.js project:
monk: Lightweight MongoDB wrappermulter: Handles multipart/form-data file uploadsgridfs-stream: Streams data to/from GridFSmongodb: Native MongoDB driver (required by gridfs-stream)
Run this command in your project directory:
npm install monk multer gridfs-stream mongodb
Monk doesn’t have built-in GridFS support, so we’ll pull the native MongoDB driver instance from Monk’s connection to set up GridFS:
const monk = require('monk'); const Grid = require('gridfs-stream'); const express = require('express'); const app = express(); // Connect to your MongoDB database const db = monk('mongodb://localhost:27017/imageStorageDB'); db.then(() => console.log('Connected to MongoDB successfully')); // Initialize GridFS let gfs; db.then((nativeDb) => { gfs = Grid(nativeDb, require('mongodb')); gfs.collection('imageUploads'); // Name your GridFS collection (can be anything) });
We’ll use Multer’s memory storage to hold uploaded files temporarily before streaming them to GridFS:
const multer = require('multer'); const storage = multer.memoryStorage(); const upload = multer({ storage: storage, limits: { fileSize: 5 * 1024 * 1024 }, // Limit files to 5MB (adjust as needed) fileFilter: (req, file, cb) => { // Only allow image files if (file.mimetype.startsWith('image/')) { cb(null, true); } else { cb(new Error('Only image files are allowed!'), false); } } });
This Express route will accept an uploaded image, stream it to GridFS, and return the stored file’s details:
// Upload route (expects a file with form field name 'image') app.post('/upload', upload.single('image'), (req, res) => { if (!req.file) { return res.status(400).send('No file was uploaded.'); } // Set up GridFS write stream const writeStream = gfs.createWriteStream({ filename: req.file.originalname, contentType: req.file.mimetype, metadata: { originalSize: req.file.size, uploadDate: new Date() } }); // Stream the uploaded file buffer to GridFS writeStream.end(req.file.buffer); // Handle stream events writeStream.on('close', (storedFile) => { res.json({ message: 'Image stored successfully!', fileId: storedFile._id.toString(), filename: storedFile.filename, contentType: storedFile.contentType }); }); writeStream.on('error', (err) => { res.status(500).send(`Failed to store image: ${err.message}`); }); });
Add routes to retrieve and serve stored images by either filename or MongoDB ObjectID:
// Get image by filename app.get('/image/:filename', (req, res) => { gfs.files.findOne({ filename: req.params.filename }, (err, file) => { if (!file || err) { return res.status(404).send('Image not found.'); } // Ensure we're serving an image if (file.contentType.startsWith('image/')) { const readStream = gfs.createReadStream(file.filename); readStream.pipe(res); } else { res.status(400).send('Requested file is not an image.'); } }); }); // Get image by MongoDB ObjectID app.get('/image/id/:id', (req, res) => { // Use monk.id() to convert string ID to MongoDB ObjectID gfs.files.findOne({ _id: monk.id(req.params.id) }, (err, file) => { if (!file || err) { return res.status(404).send('Image not found.'); } if (file.contentType.startsWith('image/')) { const readStream = gfs.createReadStream({ _id: req.params.id }); readStream.pipe(res); } else { res.status(400).send('Requested file is not an image.'); } }); }); // Start the server const PORT = 3000; app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
- Add proper error handling for MongoDB connection failures and stream errors
- Consider adding authentication to your upload/download routes
- For large files, you might want to adjust Multer’s memory limits or use disk storage instead (but ensure you clean up temporary files)
- You can add a delete endpoint using
gfs.remove({ _id: fileId }, (err) => { ... })
内容的提问来源于stack exchange,提问作者Cory Sparks

