2017-07-18 123 views
0

我在节点中有一个获取请求,成功从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结束。

这使得无法在管道后面做任何事情。什么是管道与写入流不同?

回答

4

我假设你初始化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); 
    ... 
}); 
+0

做ü认为我的方式是这样做即使响应IS实际上是utf8,字符串也是一个问题? – yoyoma

+1

@yoyoma PDF可能包含二进制数据,它们并不完全是100%UTF-8编码(PDF中的_text_可能是,但在PDF中有很多其他的东西)。 – robertklep

+0

thx很多这是工作如此标记正确 - 我曾尝试过各种缓冲区,但我不认为我正确地做了concat – yoyoma

1

如果您想在管道完成文件完成后执行某些操作,则可以在pipe返回的对象上添加finish的事件侦听器。

.pipe(fs.createWriteStream('./report.pdf')) 
.on('finish', function done() { /* the file has been written */ }); 

来源:https://nodejs.org/api/stream.html#stream_event_finish