用Node.js处理大stream

这里是我尝试使用节点和imagemagick转换工具将svgstring转换为png缓冲区。 然后使用pdfkit使用png缓冲区在pdf中绘制图像。

Td; lr我有一个大的svgstring,需要进入一个subprocess“整体”(即不分块)。 我该怎么做?

这是一个适用于小文件的例子。

var child_process = require('child_process'); var pdfDocument = require('pdfkit'); var convert = child_process.spawn("convert", ["svg:", "png:-"]), svgsrc = '<svg><rect height="100" width="100" style="fill:red;"/></svg>'; convert.stdout.on('data', function(data) { console.log(data.toString('base64') doc = new pdfDocument() doc.image(data) } convert.stdin.write(svgsrc); convert.stdin.end() 

当svgstring是'small'时(如在示例中提供的那样),这是有效的 – 我不确定从小到大的切断位置。

但是,当试图使用更大的svgstring(你可能使用D3生成的东西)像这样[ 大string ]。 我碰到:

错误:不完整或损坏的PNG文件

所以我的问题是:如何确保convertsubprocess在处理之前读取整个stream?

有几件事是已知的:

  • PNG缓冲区确实是不完整的 。 我使用了diff工具来检查应用程序生成的base64string与png-to-svg转换器的base64在线。 未损坏的string比损坏的string大得多。 (对不起,我没有更具体的文件大小)。 也就是说,转换工具似乎在任何时候都不会读取整个源文件。

  • 源svgstring没有被破坏 (正如证据显示的那样)

  • 当在命令行中使用时,转换工具正确地从一个svg“stream”生成一个PNG文件与cat large_svg.svg | convert svg:png:- cat large_svg.svg | convert svg:png:-所以这不是转换工具的问题

这导致我看到一个节点的缓冲区大小为可写和可读stream的兔子洞,但无济于事。 也许有人已经在节点中使用更大的stream,并可以帮助开始工作。

正如@mscdex所指出的那样,我不得不等待这个过程才能完成下游工作。 所有需要的是等待convert.stdoutstream上的end事件,并连接data事件上的缓冲区。

 // allocate a buffer of size 0 graph = Buffer.alloc(0) // on data concat the incoming and the `graph` convert.stdout.on('data', function(data) { graph = Buffer.concat([graph, data]) } convert.stdout.on('end', function(signal) { // ... draw on pdf } 

编辑:

这里是上面的一个更高效的版本,我们使用@mscdexbuild议在endcallback上进行连接并保持chunksize参数,以便在连接块时帮助Buffer分配大小。

 // allocate a buffer of size 0 var graph = []; var totalchunks = 0; convert.stdout.on('data', function(data) { graph.push(data); totalsize +=data.length; } convert.stdout.on('end', function(signal) { var image = Buffer.concat(graph, totalsize); // ... draw on pdf }