【问题标题】:NodeJS stream response to prevent out of memory errorsNodeJS 流响应以防止内存不足错误
【发布时间】:2014-04-06 14:17:34
【问题描述】:

我有以下代码:

 response.writeHead(200 , {
   'Content-Type': 'application/vnd.ms-excel',
   'Content-encoding': 'gzip',
   "Content-Disposition": "attachment; filename="+getFileName()
});

var zlib = require("zlib");
var data = getData(); //some arbitrary data from a method
var outputStr = "";
var header = "some header";
var footer = "some footer";

outputStr+= header;

for(i=0;i<data.length;i++) {
  outputStr+= data[i].utils.generateString(); //xml parser and various whatnots resulting in a string
}

outputStr+= footer;

zlib.gzip(outputStr, function(err, result) {
  response.end(result); //works on small strings
})

有时,我的字符串长度超过了 512mb 的限制(这很好),因此,在 32 位系统上,我会得到:

FATAL ERROR: CALL_AND_RETRY_0 Allocation failed - process out of memory

我一直在阅读有关流的内容,但是所有示例都讨论了阅读文件,而不是生成的值。

如何在迭代(我的循环)期间创建流并将数据推送到其中,而不是将其全部写入字符串并将其作为响应推送。

重要的是输出将调用文件下载,就像现在一样,以及 gzip 支持(这是异步的,因此需要考虑)

【问题讨论】:

  • 您将不得不放弃 zlib.gzip 便利功能并使用 createGzip 创建一个流并将您的数据块发送给它(最好将其输出以块的形式通过管道传输到您的响应流)。
  • 在传递“传输编码:分块”标头时出现问题?您能否提供一个涉及 createGzip 的示例(或指出一个示例)?谢谢

标签: node.js memory-management stream zlib


【解决方案1】:

您想要创建流式响应,因此您在便利函数之外创建 Gzip 流。

例子:

var zlib=require('zlib');
var fs=require('fs');

var gz=zlib.createGzip();
var res=fs.createWriteStream('./test.gz');

gz.pipe(res);

var data=['hi','test','data'];
var i;
for (i=0;i<data.length;i++) {
    gz.write(data[i]);
}
gz.end();  // this will implicitly call 'res.end()' by default

【讨论】:

  • 您好,感谢您的评论,但是,我不想将任何内容写入文件:我想将数据推送给用户。
  • 这是一个例子。在您的情况下,您已经通过 Web 请求获得了响应流。我不想编写一个完整的 http 示例,所以我使用文件作为目标。请记住,在节点中——流就是流。无论是控制台、压缩流、网络连接、文件……您都可以(大部分)对它们做同样的事情。
【解决方案2】:

如果此数据代码生成离散字符串,您应该能够在循环中使用 response.write 来实现这一点。

for(i=0;i<data.length;i++) {
  response.write(data[i].utils.generateString());
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-13
    相关资源
    最近更新 更多