2

我的应用程序正在使用节点 0.10.1、express 3.1.1、mongoose 3.6.4、mongo 2.4.1 和 gridfs-stream 0.4.0。

我已经使用共享连接设置了 mongoose 和 gridfs-stream,如下所示:

/************* app.js ***************/
//Added this in edit to show setup of mongoose and gridfs-stream
var mongoose = require("mongoose");
var Grid = require('gridfs-stream');
Grid.mongo = mongoose.mongo;
global.conn = mongoose.createConnection(dbUri);
conn.once('open', function(){
    global.gfs = Grid(conn.db);
});

我正在尝试使用 gridfs-stream 上传/下载文件。我的上传看起来像:

exports.uploadFile = function(req, res){
    var file = req.files.upload;
    var docId = mongoose.Types.ObjectId(req.query.docId);
    var filename = req.query.ileName;
    var contentType = file.type;

    if(!file) return res.send({result: 'NO_FILE_UPLOADED'});

    var writestream = gfs.createWriteStream({
        _id: docId,
        filename: filename,
        mode: 'w',
        root: 'documents'
    });
 // more here but ommitted
 };

docId 来自 mongo 文档的 ObjectId。

上传似乎工作。我可以使用 mongo 控制台查看上传的文件:

db.documents.files.findOne()
{
   "_id" : ObjectId("5167604d1b63f2541400003d"),
   "filename" : "borrower1.fnm",
   "contentType" : "binary/octet-stream",
   "length" : 3473,
   "chunkSize" : 262144,
   "uploadDate" : ISODate("2013-04-12T15:43:06.723Z"),
   "aliases" : null,
   "metadata" : null,
   "md5" : "04c85fe5e9ba0e798fd5eb90f1cb62be"
}

当我尝试下载文件时,使用以下内容:

exports.downloadFile = function(req, res){
    var docId = mongoose.Types.ObjectId(req.query.docId);
    var readstream = gfs.createReadStream({_id: docId});
    readstream.pipe(res);
};

抛出以下错误:

Error: 5167604d1b63f2541400003d does not exist

当我尝试使用似乎存储在gridfs db中的_id直接从mongo控制台检索文件时,它返回null。但是,如果我尝试使用文件名检索文件,mongo 控制台会检索该文件。

可以不使用相关mongo文档的_id设置gridfs中上传文件的_id吗?如果是这样,我的代码怎么不正确?如果没有,有没有办法让网格生成 id 并取回分配的 id,以便我可以将其存储在相关的 mongo 文档中?

谢谢你的帮助!

4

3 回答 3

5

我要回答我自己的问题,因为我在浏览 mongoose server.js 和 gridfs-stream 的源代码时找到了答案。

您可以将相关文档的 ObjectId 用于存储文件的 ObjectId。

但是,如果您在上传时提供“root”选项,您也需要在下载代码中使用它才能使用它。否则,猫鼬假定该集合是基本集合。

所以这有效:

exports.uploadFile = function(req, res){
    var file = req.files.upload;
    var docId = mongoose.Types.ObjectId(req.query.docId);
    var filename = req.query.ileName;
    var contentType = file.type;

    if(!file) return res.send({result: 'NO_FILE_UPLOADED'});

    var writestream = gfs.createWriteStream({
        _id: docId,
        filename: filename,
        mode: 'w',
        root: 'documents'
    });
 // more here but ommitted
 };

exports.downloadFile = function(req, res){
    var id = gfs.tryParseObjectId(req.query.docId);
    //note that options now includes 'root'
    var options = {_id: id, root: 'documents'};
    try{
        gfs.createReadStream(options).pipe(res);
    } catch(err){
        console.log(err);

    }
};
于 2013-04-15T20:02:39.190 回答
2

您是否尝试过将 req.query.docId 转换为 ObjectId?如果您从查询中接收值,它将是字符串,因此如果在上传期间使用了这种类型的 _id,则需要将其转换为 ObjectId。

exports.downloadFile = function(req, res){
    console.log(req.query.docId);
    var readstream = gfs.createReadStream({_id: mongoose.Types.ObjectId(req.query.docId)});
    readstream.pipe(res);
};
于 2013-04-14T20:45:52.577 回答
1

我查看了gridfs-stream页面,您是否将 mongoose 驱动程序分配给它。

var conn = mongoose.createConnection(..);
conn.once('open', function () {
  var gfs = Grid(conn.db, mongoose.mongo); //missing parameter

  // all set!
})

或者

Grid.mongo = mongoose.mongo;  //missing 

var conn = mongoose.createConnection(..);
conn.once('open', function () {
  var gfs = Grid(conn.db);

  // all set!
});
于 2013-04-12T18:41:41.150 回答