6 votes

Exception 'illegal chunk format' de MongoDB GridFS

J'ai écrit une application en Node.js qui stocke des images dans le système de fichiers GridFS de MongoDB.

J'ai téléchargé des images via l'application, et les images semblent être stockées correctement :

$ 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

Le fichier .jpg a été extrait de MongoDB et j'ai pu l'ouvrir sans problème. Il semble donc que ce que je télécharge soit stocké correctement.

Cependant, dans mon application en cours d'exécution, lorsque je tente de lire le même fichier, j'obtiens :

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

En utilisant ce code (CoffeeScript, pour 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

Il semble donc qu'il n'arrive même pas jusqu'au rappel passé à store.open().

Y a-t-il un problème pour ouvrir un fichier GridFS lorsque vous connaissez l'identifiant, mais pas le nom du fichier ?

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 

Et voici la fonction où il échoue :

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;
};

Solution

Mise à jour de la solution ici car elle ne s'affiche pas correctement dans les commentaires ci-dessous.

Le problème était la duplication ; avoir deux copies, même avec la même version, de mongodb et bson.

Heureusement, mongoose exporte le mongodb dont il a besoin en tant que propriété mongo, ce qui m'a permis de supprimer le mongodb explicite de ma page d'accueil. package.json et changé :

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

à :

mongoose = require "mongoose"
mongo = mongoose.mongo

Les choses ont maintenant l'air bien ; je pense toujours que le système de modules a besoin d'une manière sanctionnée d'accéder aux dépendances d'une dépendance (pour le cas où une dépendance n'est pas assez réfléchie pour exposer ses dépendances).

2voto

Je suis presque sûr qu'il s'agissait de copies dupliquées (même version) du module mongodb ; la suppression de node_modules et l'installation de nmp semblent avoir réglé le problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X