我想要将多个文件依次流式传输到浏览器。比如,有多个 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)
});
});
这个想法是,
- 筛选掉没有文件扩展名
.css
的所有文件。 - 筛选掉所有目录。
- 一旦一个文件完全被读取,就继续处理下一个文件。
- 将每个文件传输到响应流中,但不关闭它。
- 在所有文件被传输后结束响应流。
问题在于只有第一个.css
文件被传输,而所有剩余的文件都不见了。好像(3)在第一个(4)之后直接跳到了(5)。
有趣的是,如果我把第(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都会出现此错误。
更新
如果您按以下方式更改代码,则可以解决该问题:
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
而不是先将所有块求和,然后一次性写入?