使用Node.js管理多个文件流

问题描述 投票:3回答:2

我想将多个文件一个接一个地流式传输到浏览器。为了说明这一点,可以考虑将多个CSS文件作为一个文件连接起来。

我使用的代码是:

var directory = path.join(__dirname, 'css');
fs.readdir(directory, function (err, files) {
  async.eachSeries(files, function (file, callback) {
    if (!endsWith(file, '.css')) { return callback(); } // (1)

    var currentFile = path.join(directory, file);
    fs.stat(currentFile, function (err, stats) {
      if (stats.isDirectory()) { return callback(); } // (2)

      var stream = fs.createReadStream(currentFile).on('end', function () {
        callback(); // (3)
      });
      stream.pipe(res, { end: false }); // (4)
    });
  }, function () {
    res.end(); // (5)
  });
});

我的想法是

  1. 过滤掉所有没有文件扩展名.css的文件。
  2. 过滤掉所有目录。
  3. 完成文件读取后继续下一个文件。
  4. 将每个文件传输到响应流而不关闭它。
  5. 所有文件都通过管道传输后结束响应流。

问题是只有第一个.css文件被管道传输,所有剩余的文件都丢失了。就好像(3)会在第一个(4)之后直接跳转到(5)。

有趣的是,如果我用line替换line(4)

stream.on('data', function (data) {
  console.log(data.toString('utf8'));
});

一切都按预期工作:我看到多个文件。如果我然后将此代码更改为

stream.on('data', function (data) {
  res.write(data.toString('utf8'));
});

除第一个以外的所有文件都会再次丢失。

我究竟做错了什么?

PS:使用Node.js 0.8.7以及使用0.8.22发生错误。

UPDATE

好的,如果您按如下方式更改代码,它会起作用:

var directory = path.join(__dirname, 'css');
fs.readdir(directory, function (err, files) {
  var concatenated = '';
  async.eachSeries(files, function (file, callback) {
    if (!endsWith(file, '.css')) { return callback(); }

    var currentFile = path.join(directory, file);
    fs.stat(currentFile, function (err, stats) {
      if (stats.isDirectory()) { return callback(); }

      var stream = fs.createReadStream(currentFile).on('end', function () {
        callback();
      }).on('data', function (data) { concatenated += data.toString('utf8'); });
    });
  }, function () {
    res.write(concatenated);
    res.end();
  });
});

但为什么?为什么我不能多次调用res.write而不是先对所有块进行总结,然后立即将它们全部写入?

node.js stream
2个回答
0
投票

代码非常好,单元测试错了......

修正了,现在它就像一个魅力:-)


0
投票

还可以考虑使用multistream,它允许您一个接一个地组合和发出多个流。

© www.soinside.com 2019 - 2024. All rights reserved.