节点请求写入文件损坏

时间:2017-07-18 04:38:03

标签: node.js

我在节点中有一个成功接收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在最后触发。

管道之后无法做任何事情。什么是管道对写入流的不同做法?

2 个答案:

答案 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 */ });

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