如何使用GridFS来存储使用Node.js和Mongoose的图像

我是Node.js的新手 任何人都可以提供一个示例如何使用GridFS存储和检索二进制数据,如图像,使用Node.js和Mongoose? 我是否需要直接访问GridFS?

我对这里的最高评分答案并不满意,所以我提供了一个新的答案:我最终使用了节点模块“gridfs-stream” (很棒的文档!),可以通过npm进行安装。 有了它,并结合mongoose,它可能是这样的:

var fs = require('fs'); var mongoose = require("mongoose"); var Grid = require('gridfs-stream'); var GridFS = Grid(mongoose.connection.db, mongoose.mongo); function putFile(path, name, callback) { var writestream = GridFS.createWriteStream({ filename: name }); writestream.on('close', function (file) { callback(null, file); }); fs.createReadStream(path).pipe(writestream); } 

请注意,path是本地系统上文件的path。

至于我的文件的阅读function,对于我的情况,我只需要stream文件到浏览器(使用快递):

 try { var readstream = GridFS.createReadStream({_id: id}); readstream.pipe(res); } catch (err) { log.error(err); return next(errors.create(404, "File not found.")); } 

我build议看看这个问题: MongoDB GridFS问题与Node.JS保存文件

从答案复制的例子(功劳去christkv):

 // You can use an object id as well as filename now var gs = new mongodb.GridStore(this.db, filename, "w", { "chunk_size": 1024*4, metadata: { hashpath:gridfs_name, hash:hash, name: name } }); gs.open(function(err,store) { // Write data and automatically close on finished write gs.writeBuffer(data, true, function(err,chunk) { // Each file has an md5 in the file structure cb(err,hash,chunk); }); }); 

它看起来像writeBuffer已被弃用。

 /Users/kmandrup/private/repos/node-mongodb-native/HISTORY: 82 * Fixed dereference method on Db class to correctly dereference Db reference objects. 83 * Moved connect object onto Db class(Db.connect) as well as keeping backward compatibility. 84: * Removed writeBuffer method from gridstore, write handles switching automatically now. 85 * Changed readBuffer to read on Gridstore, Gridstore now only supports Binary Buffers no Strings anymore. 

目前为止的答案是好的,但是,我相信在这里logging如何使用官方的mongodb nodejs驱动程序而不是依赖诸如“gridfs-stream”之类的进一步抽象来实现这一点是有益的。

以前的答案确实使用了官方的mongodb驱动程序,但是他们使用了Gridstore API; 这已经被弃用,看到这里 。 我的例子将使用新的GridFSBucket API 。

问题是相当广泛的,因为我的答案将是一个完整的nodejs程序。 这将包括设置快速服务器,mongodb驱动程序,定义路由和处理GET和POST路由。

Npm使用的软件包

  • express(nodejs web应用框架来简化这个片段)
  • (用于处理多部分/表单数据请求)
  • mongodb(官方的mongodb nodejs驱动程序)

GET照片路由将Mongo ObjectID作为参数来检索图像。

我configurationmulter将上传的文件保存在内存中。 这意味着照片文件不会随时写入文件系统,而是直接从内存stream入GridFS。


 /** * NPM Module dependencies. */ const express = require('express'); const photoRoute = express.Router(); const multer = require('multer'); var storage = multer.memoryStorage() var upload = multer({ storage: storage, limits: { fields: 1, fileSize: 6000000, files: 1, parts: 2 }}); const mongodb = require('mongodb'); const MongoClient = require('mongodb').MongoClient; const ObjectID = require('mongodb').ObjectID; let db; /** * NodeJS Module dependencies. */ const { Readable } = require('stream'); /** * Create Express server && Routes configuration. */ const app = express(); app.use('/photos', photoRoute); /** * Connect Mongo Driver to MongoDB. */ MongoClient.connect('mongodb://localhost/photoDB', (err, database) => { if (err) { console.log('MongoDB Connection Error. Please make sure that MongoDB is running.'); process.exit(1); } db = database; }); /** * GET photo by ID Route */ photoRoute.get('/:photoID', (req, res) => { try { var photoID = new ObjectID(req.params.photoID); } catch(err) { return res.status(400).json({ message: "Invalid PhotoID in URL parameter. Must be a single String of 12 bytes or a string of 24 hex characters" }); } let bucket = new mongodb.GridFSBucket(db, { bucketName: 'photos' }); let downloadStream = bucket.openDownloadStream(photoID); downloadStream.on('data', (chunk) => { res.write(chunk); }); downloadStream.on('error', () => { res.sendStatus(404); }); downloadStream.on('end', () => { res.end(); }); }); /** * POST photo Route */ photoRoute.post('/', (req, res) => { upload.single('photo')(req, res, (err) => { if (err) { return res.status(400).json({ message: "Upload Request Validation Failed" }); } else if(!req.body.name) { return res.status(400).json({ message: "No photo name in request body" }); } let photoName = req.body.name; // Covert buffer to Readable Stream const readablePhotoStream = new Readable(); readablePhotoStream.push(req.file.buffer); readablePhotoStream.push(null); let bucket = new mongodb.GridFSBucket(db, { bucketName: 'photos' }); let uploadStream = bucket.openUploadStream(photoName); let id = uploadStream.id; readablePhotoStream.pipe(uploadStream); uploadStream.on('error', () => { return res.status(500).json({ message: "Error uploading file" }); }); uploadStream.on('finish', () => { return res.status(201).json({ message: "File uploaded successfully, stored under Mongo ObjectID: " + id }); }); }); }); app.listen(3005, () => { console.log("App listening on port 3005!"); }); 

我写了一篇关于这个主题的博客文章。 是我的答案的阐述。 可在这里

进一步阅读/启示:

  • NodeJsstream:你需要知道的一切
  • Multer NPM文档
  • Nodejs的MongoDB驱动程序