我有两台相互通信的服务器。 Server1从Server2请求部分文件,并将接收的数据存储到一个文件中。 Server2应该接收这些请求中的每一个,并创建一个流管道数据的流。
假设服务器2中存储的文件(目录)如下:
bigfile.gz
bigfile.gz.part-0
bigfile.gz.part-1
bigfile.gz.part-2
......
因此Server1将发送对part-0然后part-1的请求,依此类推到Server2。因此使用循环来发出请求。
服务器1(代码段)
for (var i in requestInfo['blockName']) {
var blockName = i;
var IP = requestInfo['blockName'][i][0];
var fileData = JSON.stringify({
blockName: blockName,
fileName: requestInfo['fileName']
});
makeRequest(fileData, IP);
console.log(counter);
}
function makeRequest(fileData, IP) {
var options = {
host: IP,
port: 5000,
path: '/read',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
var req = http.request(options, function(res) {
var data = '';
res.on('data', function(chunk) {
data += chunk;
});
res.on('end', function() {
console.log(data.length);
//fs.appendFileSync(fileName, data);
var writeStream = fs.createWriteStream(fileName, { "flags": 'a' });
writeStream.write(data);
writeStream.end();
});
});
req.write(fileData);
req.end();
}
服务器2(代码段)
app.post('/read', function(req, res) {
var dataBody = req.body;
fs.createReadStream(dataBody.fileName + '/' + dataBody.blockName).pipe(res);
});
上面的一个适用于我用100MB txt文件测试的时候。但是当我有1GB .gz文件时,或者当我用.zip文件测试它时,在服务器1端生成的最终.zip的输出是不正确的大小,它失败了。
我不确定我在这里做错了什么,或者是替代解决方案
修改
在处理大的1GB .gz文件时,我的Server1也崩溃了
答案 0 :(得分:1)
这里的主要问题是您通过将chunks
附加到字符串来将数据视为字符串。
通过重写,这应该是
var req = http.request(options, function(res) {
var data = [];
res.on('data', function(chunk) {
data.push(chunk);
});
res.on('end', function() {
fs.writeFile(fileName, Buffer.concat(data), function() {
console.log("write end")
});
});
});
这样我们就可以创建一个 big 二进制块数组,当下载完成后,我们将所有块的串联写入文件。
但请注意大字
如果您坚持使用此实现,则可能会出现内存不足的问题,尤其是在处理大型(> 500mb)文件时。
救援流
var req = https.request(options, function(res) {
res.pipe(fs.createWriteStream(fileName)).on("close", function() {
console.log("write end");
});
});
使用上述实现内存占用率应保持低水平。因为从下载中获取特定数量的数据,您可以将它们写入文件。这样你就不会将整个文件保存到程序的内存中。