如何使用multer-gridfs-storage,express,mongodb在用户configuration文件中添加图像path

下面是我的file upload代码

/** Setting up storage using multer-gridfs-storage */ var storage = GridFsStorage({ gfs : gfs, filename: function (req, file, cb) { var datetimestamp = Date.now(); cb(null, file.fieldname + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length -1]); }, /** With gridfs we can store aditional meta-data along with the file */ metadata: function(req, file, cb) { cb(null, { originalname: file.originalname }); }, root: 'ctFiles' //root name for collection to store files into }); var upload = multer({ //multer settings for single upload storage: storage }).single('file'); /** API path that will upload the files */ app.post('/upload', function(req, res) { upload(req,res,function(err){ if(err){ res.json({error_code:1,err_desc:err}); return; } console.log(res.file); console.log(res[0].file); res.json({error_code:0,err_desc:null}); }); }); 

我想在用户集合中存储用户名,电子邮件和文件path,这是我的UserSchema

 var UserSchema = new Schema({ name: String, email: { type: String, lowercase: true }, filepath: String, }); 

这是图像如何存储在集合中

 { "_id" : ObjectId("58fb894111387b23a0bf2ccc"), "filename" : "file-1492879681306.PNG", "contentType" : "image/png", "length" : 67794, "chunkSize" : 261120, "uploadDate" : ISODate("2017-04-22T16:48:01.350Z"), "aliases" : null, "metadata" : { "originalname" : "Front.PNG" }, "md5" : "404787a5534d0479bd55b2793f2a74b5" } 

这是我的期望结果:在用户集合我应该得到这样的数据

 { "name" :"asdf", "email" : "asdf@gmail.com", "filepath":"file/file-1492879681306.PNG" } 

在GridFS中存储和在一个普通的MongoDb集合中存储是有区别的。 第一个是devise用来有效地存储文件 ,可select任何附加信息,而后者允许你设置任何模式并存储任何信息 。 你不能以同样的方式处理。

如果你想在你的应用程序中build立一个文件和一个模式之间的关系,你可以这样做。

  1. 将所需的模式信息存储在文件的元数据中

    Pro:所有附加数据都存储在文件中,删除文件会自动清除附加信息。

    Con:查询可能变得复杂,因为所有查询都必须以metadata字段作为前缀,并将所有信息混合在一起。

    这可能是你的一个文件的输出

     { "_id" : ObjectId("58fb894111387b23a0bf2ccc"), "filename" : "file-1492879681306.PNG", "contentType" : "image/png", "length" : 67794, "chunkSize" : 261120, "uploadDate" : ISODate("2017-04-22T16:48:01.350Z"), "aliases" : null, "metadata" : { "originalname" : "Front.PNG", "name" :"asdf", "email" : "asdf@gmail.com", "filepath":"file/file-1492879681306.PNG" }, "md5" : "404787a5534d0479bd55b2793f2a74b5" } 

    像这样设置信息很简单,只需要稍微改变一下metadatafunction即可。

     .... /** With gridfs we can store aditional meta-data along with the file */ metadata: function(req, file, cb) { var metadata = { originalname: file.originalname, // get this information somehow name :"asdf", email : "asdf@gmail.com", filepath:"file/file-1492879681306.PNG" }; cb(null, metadata); }, .... 

    这就是你应该如何访问他们,尽pipe你可以使用db.collectionMongoose来达到同样的目的。

     const mongodb = require('mongodb'); const GridFSBucket = mongodb.GridFSBucket; const MongoClient = mongodb.MongoClient; MongoClient.connect('mongodb://yourhost:27017/database').then((db) => { const bucket = new GridFSBucket(db, {bucketName: 'ctFiles'}); bucket .find({metadata: {'email' : 'asdf@gmail.com'}}) .toArray() .then((fileInfoArr) => { console.log(fileInfoArr); }); }); 

    然后,您可以使用fileInfo数组创buildstream并读取文件。

  2. 独立存储模式并添加一个指向存储文件的ID的ObjectId字段。

    专业版:查询和更新您的UserSchema更容易编写和理解,因为模式定义存储在不同的集合。

    答:现在你有两个集合担心,必须手动保持同步; 当一个文件被删除时,你应该删除用户数据,反之亦然。

    这就是你的UserSchema样子

      var UserSchema = new Schema({ name: String, email: { type: String, lowercase: true }, filepath: String, fileId: Schema.Types.ObjectId }); 

    这就是你如何访问文件

     UserModel.findOne({'email' : 'asdf@gmail.com'}, function (err, user) { // deal with error // store and get the db object somehow const bucket = new GridFSBucket(db, {bucketName: 'ctFiles'}); // A download stream reads the file from GridFs const readStream = bucket.openDownloadStream(user.fileId)); readStream.pipe(/* some writable stream */); }); 

请记住,GridF存储文件,因此应尽可能使用stream来正确读写数据处理背压 。

PD:

root这样的东西属于过时的GridStore 。 尽可能使用GridFSBucket 。 新版本的multer-gridfs-storage也处理bucketName而不是root