MongoDB GridFS的“非法块格式”exception

我一直在Node.js上编写一个应用程序,用于将图像存储在MongoDB的GridFS文件系统中。

我已经通过应用上传图片,并且图片显示为正确存储:

$ mongofiles -v -d speaker-karaoke get howard-basement-100x115.jpg Tue Jul 17 12:14:16 creating new connection to:127.0.0.1 Tue Jul 17 12:14:16 BackgroundJob starting: ConnectBG Tue Jul 17 12:14:16 connected connection! connected to: 127.0.0.1 done write to: howard-basement-100x115.jpg 

这抓住了MongoDB的.jpg,我可以打开它没有问题,所以它看起来像我上传正在正确存储。

但是,在我正在运行的应用程序中,当我尝试读取同一个文件时,我得到:

 12:15:44 web.1 | started with pid 89621 12:15:45 web.1 | Connecting to mongodb://localhost/speaker-karaoke 12:15:45 web.1 | Speaker Karaoke express app started on 5000 12:15:48 web.1 | DEBUG: Get review thumbnail for 5005b7550333650000000001 12:15:48 web.1 | 12:15:48 web.1 | node.js:201 12:15:48 web.1 | throw e; // process.nextTick error, or 'error' event on first tick 12:15:48 web.1 | ^ 12:15:48 web.1 | Error: Illegal chunk format 12:15:48 web.1 | at Error (unknown source) 12:15:48 web.1 | at new <anonymous> (/Users/hlship/workspaces/github/speaker-karaoke/node_modules/mongodb/lib/mongodb/gridfs/chunk.js:43:11) 12:15:48 web.1 | at /Users/hlship/workspaces/github/speaker-karaoke/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js:488:24 12:15:48 web.1 | at Cursor.nextObject (/Users/hlship/workspaces/github/speaker-karaoke/node_modules/mongoose/node_modules/mongodb/lib/mongodb/cursor.js:462:5) 12:15:48 web.1 | at [object Object].<anonymous> (/Users/hlship/workspaces/github/speaker-karaoke/node_modules/mongoose/node_modules/mongodb/lib/mongodb/cursor.js:456:12) 12:15:48 web.1 | at [object Object].g (events.js:156:14) 12:15:48 web.1 | at [object Object].emit (events.js:88:20) 12:15:48 web.1 | at Db._callHandler (/Users/hlship/workspaces/github/speaker-karaoke/node_modules/mongoose/node_modules/mongodb/lib/mongodb/db.js:1290:25) 12:15:48 web.1 | at /Users/hlship/workspaces/github/speaker-karaoke/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:329:30 12:15:48 web.1 | at [object Object].parseBody (/Users/hlship/workspaces/github/speaker-karaoke/node_modules/mongoose/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js:118:5) 12:15:48 web.1 | process terminated 12:15:48 system | sending SIGTERM to all processes 

使用这个代码(CoffeeScript,用于Express):

  app.get "/images/review-thumbnail/:id", (req, res) -> id = req.params.id util.debug "Get review thumbnail for #{id}" store = new GridStore mongoose.connection.db, new ObjectID(id), null, "r" store.open (err, file) -> throw err if err util.debug "Store open for #{id}, type = #{file.contentType}" # TODO: Scale the image before sending it! res.header "Content-Type", file.contentType store.stream(true).pipe res 

所以它似乎甚至不会传递给store.open()的callback。

当你知道id而不是文件名时,是否有打开GridFS文件的问题?

BTW:

 $ npm ls speaker-karaoki@0.0.1 /Users/hlship/workspaces/github/speaker-karaoke ├─┬ blueimp-file-upload-node@1.0.2 extraneous │ ├── formidable@1.0.11 │ ├── imagemagick@0.1.2 │ └── node-static@0.6.0 ├── coffee-script@1.3.3 ├─┬ connect-assets@2.1.9 │ ├── connect-file-cache@0.2.4 │ ├── mime@1.2.2 │ ├─┬ snockets@1.3.4 │ │ ├── coffee-script@1.3.3 │ │ ├── dep-graph@1.0.1 │ │ └── uglify-js@1.0.7 │ └── underscore@1.1.7 ├─┬ express@2.5.9 │ ├─┬ connect@1.9.1 │ │ └── formidable@1.0.11 │ ├── mime@1.2.4 │ ├── mkdirp@0.3.0 │ └── qs@0.4.2 ├─┬ jade@0.26.0 │ ├── commander@0.5.2 │ └── mkdirp@0.3.0 ├─┬ mongodb@1.0.2 │ └── bson@0.0.6 ├─┬ mongoose@2.7.0 │ ├── hooks@0.2.1 │ └─┬ mongodb@1.0.2 │ └── bson@0.0.6 ├─┬ passport@0.1.10 │ └── pkginfo@0.2.3 ├─┬ passport-twitter@0.1.3 │ ├─┬ passport-oauth@0.1.9 │ │ ├── oauth@0.9.7 │ │ └── passport@0.1.11 │ └── pkginfo@0.2.3 ├── sass@0.5.0 └── underscore@1.3.3 

这里是失败的function:

 var Chunk = exports.Chunk = function(file, mongoObject) { if(!(this instanceof Chunk)) return new Chunk(file, mongoObject); this.file = file; var self = this; var mongoObjectFinal = mongoObject == null ? {} : mongoObject; this.objectId = mongoObjectFinal._id == null ? new ObjectID() : mongoObjectFinal._id; this.chunkNumber = mongoObjectFinal.n == null ? 0 : mongoObjectFinal.n; this.data = new Binary(); if(mongoObjectFinal.data == null) { } else if(typeof mongoObjectFinal.data == "string") { var buffer = new Buffer(mongoObjectFinal.data.length); buffer.write(mongoObjectFinal.data, 'binary', 0); this.data = new Binary(buffer); } else if(Array.isArray(mongoObjectFinal.data)) { var buffer = new Buffer(mongoObjectFinal.data.length); buffer.write(mongoObjectFinal.data.join(''), 'binary', 0); this.data = new Binary(buffer); } else if(mongoObjectFinal.data instanceof Binary || Object.prototype.toString.call(mongoObjectFinal.data) == "[object Binary]") { this.data = mongoObjectFinal.data; } else if(Buffer.isBuffer(mongoObjectFinal.data)) { } else { throw Error("Illegal chunk format"); } // Update position this.internalPosition = 0; }; 

在这里更新解决scheme,因为它不能在下面的注释中正确显示。

问题是重复; 有两个副本,即使是相同版本的mongodb和bson。

幸运的是,mongoose将它需要的mongodb作为属性mongo导出,所以我可以从package.json删除显式的mongodb并更改:

 mongo = require "mongodb" mongoose = require "mongoose" 

至:

 mongoose = require "mongoose" mongo = mongoose.mongo 

事情现在好看; 我仍然认为模块系统需要一个认可的方式来访问一个依赖依赖关系(对于一个dep不够周到的情况下公开它的代表)。

确定它是mongodb模块的重复副本(相同版本); 删除node_modules和NMP安装似乎已经修复它。