我在节点中有一个成功接收API数据的get请求。
当我将该响应直接传递给这样的文件时,它可以工作,创建的文件是一个有效的,可读的pdf(正如我希望从API接收的那样)。
var http = require('request');
var fs = require('fs');
http.get(
{
url:'',
headers:{}
})
.pipe(fs.createWriteStream('./report.pdf'));
很简单,但是如果我使用像这样的请求的事件发射器
,则文件会被破坏 http.get(
{
url:'',
headers:{}
})
.on('error', function (err) {
console.log(err);
})
.on('data', function(data) {
file += data;
})
.on('end', function() {
var stream = fs.createWriteStream('./report.pdf');
stream.write(file, function() {
stream.end();
});
});
我已尝试过编写此文件的所有方式,它始终以完全空白的pdf结尾 - pdf有效的唯一时间是通过管道方法。
当我控制台记录事件时,序列似乎是正确的 - 即,所有接收的块然后end
在最后触发。
管道之后无法做任何事情。什么是管道对写入流的不同做法?
答案 0 :(得分:5)
我假设您将file
初始化为字符串:
var file = '';
然后,在您的data
处理程序中,向其添加新的数据块:
file += data;
但是,这会执行到(UTF-8编码)字符串的隐式转换。如果数据实际上是二进制的,就像使用PDF一样,这将使输出数据无效。
相反,您希望收集data
个块,这些块是Buffer
个实例,并使用Buffer.concat()
将所有缓冲区连接到一个大型(二进制)缓冲区中:
var file = [];
...
.on('data', function(data) {
file.push(data);
})
.on('end', function() {
file = Buffer.concat(file);
...
});
答案 1 :(得分:2)
如果您想在通过管道写入文件后执行某些操作,则可以在管道返回的对象上为finish
添加事件侦听器。
.pipe(fs.createWriteStream('./report.pdf'))
.on('finish', function done() { /* the file has been written */ });