从另一台服务器

时间:2018-03-14 07:52:10

标签: javascript node.js

我有两台相互通信的服务器。 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也崩溃了

1 个答案:

答案 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");
  });
});

使用上述实现内存占用率应保持低水平。因为从下载中获取特定数量的数据,您可以将它们写入文件。这样你就不会将整个文件保存到程序的内存中。