我想将多个文件一个接一个地传输到浏览器。为了说明这一点,可以考虑将多个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)。
有趣的是,如果我用
替换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发生错误。
更新
好的,如果您按如下方式更改代码,它会起作用:
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
而不是先对所有块进行求和,然后立即将它们全部写出来?
答案 0 :(得分:0)
代码非常好,单元测试错了......
修正了,现在它就像魅力一样: - )
答案 1 :(得分:0)
还考虑使用multistream,它使您可以合并并一个接一个地发射多个流。
答案 2 :(得分:0)
可以帮助别人:
const fs = require("fs");
const pth = require("path");
let readerStream1 = fs.createReadStream(pth.join(__dirname, "a.txt"));
let readerStream2 = fs.createReadStream(pth.join(__dirname, "b.txt"));
let writerStream = fs.createWriteStream(pth.join(__dirname, "c.txt"));
//only readable streams have "pipe" method
readerStream1.pipe(writerStream);
readerStream2.pipe(writerStream);
我还检查了 Rocco 的 答案,并且它的效果非常好:
//npm i --save multistream
const multi = require('multistream');
const fs = require('fs');
const pth = require("path");
let streams = [
fs.createReadStream(pth.join(__dirname, "a.txt")),
fs.createReadStream(pth.join(__dirname, "b.txt"))
];
let writerStream = fs.createWriteStream(pth.join(__dirname, "c.txt"));
//new multi(streams).pipe(process.stdout);
new multi(streams).pipe(writerStream);
并将结果发送给客户端:
const multi = require('multistream');
const fs = require('fs');
const pth = require("path");
const exp = require("express");
const app = exp();
app.listen(3000);
app.get("/stream", (q, r) => {
new multi([
fs.createReadStream(pth.join(__dirname, "a.txt")),
fs.createReadStream(pth.join(__dirname, "b.txt"))
]).pipe(r);
});