来自readstream的'end'事件发出两次

时间:2014-02-21 09:25:20

标签: node.js gridfs

我正在尝试将文件上传到nodejs中的mongodb的gridfs。这是我的一段代码:

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()是其他一些功能。

问题是,在日志中,我看到file upload finished出现两次而stream opened只出现一次

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

这导致doCSUpdate()运行两次,有时会导致Can't set headers after they are sent错误,因为响应设置了两次..

1 个答案:

答案 0 :(得分:0)

我知道这已经晚了但是认为它可能对未来的搜索者有用。

也许[文件上传完成]消息出现两次,因为上传是以块的形式完成的,就像你向GridFS上传任何大小合适的内容一样。快速解决方法是使用guard子句来阻止函数再次运行。

我更早地遇到了这个问题,当读取流的'data'事件多次发出导致Node抱怨[错误:发送后无法设置标头]。像下面这样简单的东西可能会有所帮助。

var doCSUpdateAlreadyCalled = false;
...
if (! doCSUpdateAlreadyCalled){
   doCSUpdateAlreadyCalled = true;
   doCSUpdate();
}