首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当使用mongoose、gridfs-stream和multer上传文件时,MongoError

当使用mongoose、gridfs-stream和multer上传文件时,MongoError
EN

Stack Overflow用户
提问于 2014-11-26 19:39:52
回答 2查看 4K关注 0票数 3

我正在使用穆特网格流猫鼬与mongodb一起运行express 4,并试图上传一个文件并将其流到gridfs。

这样做的特快路线被定义为:

代码语言:javascript
复制
app.post('/uploadfile', function (req, res) {
    console.dir(req.files);

    // The mongodb instance created when the mongoose.connection is opened
    var db = mongoose.connection.db;

    // The native mongo driver which is used by mongoose
    var mongoDriver = mongoose.mongo;

    // Create a gridfs-stream
    var gfs = new Gridfs(db, mongoDriver);

    var file = req.files.myFile;

    var fileId = new ObjectId();

    console.log("Creating WriteStream");
    var writeStream = gfs.createWriteStream({
        _id: fileId,
        filename: file.originalname,
        mode: 'w',
        content_type: file.mimetype,
        metadata: {
            id: '123',
            number: '2',
            name: "Kenny Erasmuson"
        }
     });
     console.log("Created WriteStream");
     req.pipe(writeStream);
     console.log("Finished!");
});

快速应用程序运行后,将选择并上传一个文件(通过HTML多部分/表单-数据表单),节点服务器的输出为:

代码语言:javascript
复制
$ node server.js 
Listening on port 8001
{ myFile: 
    { fieldname: 'myFile',
    originalname: 'kenny-credit-rating.pdf',
    name: '1082e5071ede1002c4ae5be6123226d8.pdf',
    encoding: '7bit',
    mimetype: 'application/pdf',
    path: 'uploads/1082e5071ede1002c4ae5be6123226d8.pdf',
    extension: 'pdf',
    size: 110782,
    truncated: false,
    buffer: null } 
}
Creating WriteStream
Created WriteStream
Finished!
/Users/kenny/Dropbox/Dev/fileUploader/node_modules/mongoose/node_modules/mongodb/lib/mongodb/co nnection/base.js:246
    throw message;      
          ^
MongoError: The dollar ($) prefixed field '$conditionalHandlers' in '_id.$conditionalHandlers' is not valid for storage.
at Object.toError (/Users/kenny/Dropbox/Dev/fileUploader/node_modules/mongoose/node_modules/mongodb/lib/mongodb/utils.js:114:11)
at /Users/kenny/Dropbox/Dev/fileUploader/node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection/core.js:569:27
at /Users/kenny/Dropbox/Dev/fileUploader/node_modules/mongoose/node_modules/mongodb/lib/mongodb/db.js:1157:7
at /Users/kenny/Dropbox/Dev/fileUploader/node_modules/mongoose/node_modules/mongodb/lib/mongodb/db.js:1890:9
at Server.Base._callHandler (/Users/kenny/Dropbox/Dev/fileUploader/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/base.js:448:41)
at /Users/kenny/Dropbox/Dev/fileUploader/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:481:18
at MongoReply.parseBody (/Users/kenny/Dropbox/Dev/fileUploader/node_modules/mongoose/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js:68:5)
at null.<anonymous> (/Users/kenny/Dropbox/Dev/fileUploader/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:439:20)
at emit (events.js:95:17)
at null.<anonymous> (/Users/kenny/Dropbox/Dev/fileUploader/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_pool.js:201:13)

有没有人知道是什么导致了错误,以及如何修复?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-11-27 17:28:05

在我的代码中:

代码语言:javascript
复制
var fileId = new ObjectId();

console.log("Creating WriteStream");
var writeStream = gfs.createWriteStream({
    _id: fileId,
    filename: file.originalname,
    mode: 'w',
    content_type: file.mimetype,
    metadata: {
        id: '123',
        number: '2',
        name: "Kenny Erasmuson"
    }
 });

我将向传递给ObjectId的对象的_id属性分配ObjectId的字符串表示形式,而不是分配给gfs.createWriteStream。结果,这导致了我的代码中的MongoError。

已发现的这里修复程序是更改代码行,导致问题如下:

代码语言:javascript
复制
_id: fileId.str,

完成了这些工作之后,我开始讨论文件没有被放入fs.chunks mongodb集合的问题,尽管元数据最终会在fs.files mongodb集合中结束。AddieD的回答这里开始解决以下问题:)

票数 2
EN

Stack Overflow用户

发布于 2014-11-27 05:41:34

问题在于,您不只是向gridfs流发送文件请求。使用Multer作为中间件,捕获任何multipart/form-data post请求。当流进来时,Multer (构建在勤杂工上)监视on('field')on('file')事件并进行相应的分析。你给穆特的不仅仅是一个文件。

这段代码运行良好,因为穆特确实已经为您解析了req.filesreq.body

代码语言:javascript
复制
   // Create a gridfs-stream
   var gfs = new Gridfs(db, mongoDriver);

   var file = req.files.myFile;

   var fileId = new ObjectId();

   console.log("Creating WriteStream");
   var writeStream = gfs.createWriteStream({
        _id: fileId,
        filename: file.originalname,
        mode: 'w',
        content_type: file.mimetype,
        metadata: {
            id: '123',
            number: '2',
            name: "Kenny Erasmuson"
        }
     });
     console.log("Created WriteStream");

但是,由于上述原因,您的代码在这里遇到了问题:

代码语言:javascript
复制
 req.pipe(writeStream);

我还没有找到一种方法来流多部分/表单数据的post请求,不仅仅是将文件上传到GridFS。如果post请求不包含文件以外的任何内容(意味着表单中没有其他html输入字段),那么您可能需要考虑将Multer从中间件中删除,至少在此路由中是这样的。

对于我的用例,我需要能够接收带有文本输入和文件上传的html表单帖子(我在上传时存储有关文件的元数据)。下面是我如何在穆特身上完成我所需要的:

代码语言:javascript
复制
var uploadImg = function(req,res) {
      var writestream = gfs.createWriteStream({
        filename: req.files.file.name,
        mode:'w',
        content_type:req.files.file.mimetype,
        metadata:req.body,
      });
    fs.createReadStream(req.files.file.path).pipe(writestream);

    writestream.on('close', function (file) {
        res.send("Success!");
        fs.unlink(req.files.file.path, function (err) {
          if (err) console.error("Error: " + err);
          console.log('successfully deleted : '+ req.files.file.path );
        });
    });

};

默认情况下,Multer会将您的文件存储在磁盘上。一个快速的解决方案就是创建一个readstream并将其流回GridFS。写完后,删除tmp文件。

顺便提一句,似乎有一些想法认为,最好只在需要它的路线上使用Multer作为中间件。您可以在的最后一节中阅读更多关于这一思想的内容。

更新

我想我已经接近找到一种通过使用GridFS使用船长直接流到元数据的方法了。我正在查看是否无法对船长-格雷斯进行一些更新,这些更新将接受html表单上的文本输入,并将其设置为元数据,等等。当它被冲走的时候我会更新的。如果您查看船长,一定要确认您的html表单输入的顺序(如果有)确实很重要。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27157565

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档