0

I'm trying to make file uploading to mongodb's gridfs in nodejs. Here's a piece of my code:

var fs = require('fs');
var gridfs = require('gridfs-stream');
var mongo = require('mongodb');
var gfs;

mongo.Db.connect('mongodb://...', function (err, db) {
    console.log('*** connect to upload files');
    gfs = gridfs(db, mongo);

    var fpath = req.files.image_file.path;
    var fname = id + '_' + req.files.image_file.name;
    console.log('*** final name = ' + fname);

    var writestream = gfs.createWriteStream({ filename: fname });
    var readstream = fs.createReadStream(fpath);

    readstream.on('open', function () {
        console.log('*** stream opened');
        readstream.pipe(writestream);
    });
    readstream.on('end', function () {
        console.log('*** file upload finished');
        doCSUpdate();
    });
    readstream.on('error', function() {
        console.log('*** error occured');
        doCSUpdate();
    });
});

doCSUpdate() is some other function.

The problem is that in logs I see that file upload finished appears twice while stream opened only once

13:21:30 web.1  | *** connect to upload files
13:21:30 web.1  | *** final name = ...
13:21:30 web.1  | *** stream opened
13:21:30 web.1  | *** file upload finished
13:21:30 web.1  | *** file upload finished

This causes doCSUpdate() to be run twice which sometimes leads to Can't set headers after they are sent error because the response is set two times..

xaxa
  • 1,057
  • 1
  • 24
  • 53
  • I'm using similar code, although I'm watching for the `close` event on the writable stream, instead of the `end` stream of the readable stream. I don't know why the `end` would get triggered twice, though. – robertklep Feb 21 '14 at 10:12
  • @robertklep, Does it work fine? As I understand from docs http://nodejs.org/api/stream.html#stream_event_close not every stream emits `close` event. But it doesn't describe which streams do and which don't... – xaxa Feb 21 '14 at 10:23
  • Yes, works fine for me (similar situation: storing files uploaded through Express in GridFS). – robertklep Feb 21 '14 at 12:21

1 Answers1

0

I know this is late but thought it might be useful for future searchers.

Perhaps the [file upload finished] message appeared twice because the uploads were done in chunks as is the case when you upload anything of decent size to GridFS. Quick workaround would be to use a guard clause to prevent the function from running again.

I faced this problem earlier when the 'data' event of the readstream was emitted more than once causing Node to complain that [Error: Can't set headers after they are sent]. Something simple like the following might help.

var doCSUpdateAlreadyCalled = false;
...
if (! doCSUpdateAlreadyCalled){
   doCSUpdateAlreadyCalled = true;
   doCSUpdate();
}
umun
  • 11
  • 2