节点请求写入文件损坏
问题描述:
我在节点中有一个获取请求,成功从API接收数据。节点请求写入文件损坏
当我将这种响应直接传递给像这样的文件时,它可以工作,创建的文件是一个有效的,可读的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
结束。
这使得无法在管道后面做任何事情。什么是管道与写入流不同?
答
我假设你初始化file
作为一个字符串:
var file = '';
然后,在你data
处理程序,数据的新块添加到它:
file += data;
然而,这执行一个im plicit转换为(UTF-8编码)字符串。如果数据实际上是二进制的,就像使用PDF一样,这会使输出数据无效。
相反,你要收集的data
块,这是Buffer
实例,并使用Buffer.concat()
所有这些缓冲区连接成一个大的(二进制)缓冲液:
var file = [];
...
.on('data', function(data) {
file.push(data);
})
.on('end', function() {
file = Buffer.concat(file);
...
});
答
如果您想在管道完成文件完成后执行某些操作,则可以在pipe返回的对象上添加finish
的事件侦听器。
.pipe(fs.createWriteStream('./report.pdf'))
.on('finish', function done() { /* the file has been written */ });
做ü认为我的方式是这样做即使响应IS实际上是utf8,字符串也是一个问题? – yoyoma
@yoyoma PDF可能包含二进制数据,它们并不完全是100%UTF-8编码(PDF中的_text_可能是,但在PDF中有很多其他的东西)。 – robertklep
thx很多这是工作如此标记正确 - 我曾尝试过各种缓冲区,但我不认为我正确地做了concat – yoyoma