使用 Node.js 处理大型流
Handling Large stream with Node.js
我尝试使用节点和 imagemagick 转换工具将 svg 字符串转换为 png 缓冲区。然后使用 pdfkit 使用 png 缓冲区在 pdf 中绘制图像。
Td;lr 我有一个大的 svg 字符串需要到达子进程 "whole"(即不分块)。我该怎么做?
这是一个适用于小文件的示例。
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()
这在 svg 字符串为 'small' 时有效(如示例中提供的 on)——我不确定从小到大的截止点在哪里。
但是,当尝试像这样使用更大的 svg 字符串(您可能使用 D3 生成的字符串)时 [large string]。我运行进入:
Error: Incomplete or corrupt PNG file
所以我的问题是:如何确保convert
子进程在处理之前读取整个流?
有几件事是已知的:
png 缓冲区确实不完整。我使用差异工具来检查
应用程序生成的 base64 字符串
与在线 png-to-svg 转换器的 base64 相比。未腐败的
字符串比损坏的字符串大得多。 (抱歉我没有
文件大小更具体)。也就是说,转换工具似乎
不要在任何给定时间阅读整个来源。
源 svg 字符串未损坏(事实证明
要点呈现它)
在命令行中使用时,转换工具会正确生成
来自 svg "stream" 和 cat large_svg.svg | convert svg:png:-
的 png 文件 所以这不是转换工具的问题。
这让我陷入了寻找可写和可读流的节点缓冲区大小的困境,但无济于事。也许有人在节点中使用过更大的流,可以帮助它工作。
正如@mscdex 指出的那样,我必须等待进程完成
尝试下游工作。所需要做的就是等待 convert.stdout
流上的 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
}
编辑:
这是我们使用@mscdex 的更高效的版本
建议在 end
回调上进行连接并保留 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
}
我尝试使用节点和 imagemagick 转换工具将 svg 字符串转换为 png 缓冲区。然后使用 pdfkit 使用 png 缓冲区在 pdf 中绘制图像。
Td;lr 我有一个大的 svg 字符串需要到达子进程 "whole"(即不分块)。我该怎么做?
这是一个适用于小文件的示例。
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()
这在 svg 字符串为 'small' 时有效(如示例中提供的 on)——我不确定从小到大的截止点在哪里。
但是,当尝试像这样使用更大的 svg 字符串(您可能使用 D3 生成的字符串)时 [large string]。我运行进入:
Error: Incomplete or corrupt PNG file
所以我的问题是:如何确保convert
子进程在处理之前读取整个流?
有几件事是已知的:
png 缓冲区确实不完整。我使用差异工具来检查 应用程序生成的 base64 字符串 与在线 png-to-svg 转换器的 base64 相比。未腐败的 字符串比损坏的字符串大得多。 (抱歉我没有 文件大小更具体)。也就是说,转换工具似乎 不要在任何给定时间阅读整个来源。
源 svg 字符串未损坏(事实证明 要点呈现它)
在命令行中使用时,转换工具会正确生成 来自 svg "stream" 和
cat large_svg.svg | convert svg:png:-
的 png 文件 所以这不是转换工具的问题。
这让我陷入了寻找可写和可读流的节点缓冲区大小的困境,但无济于事。也许有人在节点中使用过更大的流,可以帮助它工作。
正如@mscdex 指出的那样,我必须等待进程完成
尝试下游工作。所需要做的就是等待 convert.stdout
流上的 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
}
编辑:
这是我们使用@mscdex 的更高效的版本
建议在 end
回调上进行连接并保留 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
}