Node.js - createWriteStream正在写一个与writeFile不同的文件

时间:2017-01-22 13:02:52

标签: node.js stream

我正在尝试使用HTTP GET请求远程下载MP4文件。当HTTP GET响应被压缩到文件时,文件写得很完美(~3MB)。

request.get('http://url.tld/video.mp4').pipe(fs.createWriteStream('video.mp4'))

但是,当fs.writeFileSync函数正在写入HTTP GET响应主体时,它会创建一个更大的文件(~7MB),并且因为它已经损坏而无法执行。

request.get('http://url.tld/video.mp4', function(err, res, body){
    fs.writeFileSync('./video.mp4', body)
});

为什么会这样?管道功能是否为相应的文件设置了正确的编码?

2 个答案:

答案 0 :(得分:0)

是的,它是编码。在写入文件而不是管道传输时,在写入文件之前,正文流将使用utf8编码转换为Buffer对象。

只是一个简单的实验来证明这一点。

检查下载的流的长度

var streamlen = 0;

request.get('http://url.tld/video.mp4')
.on('data', function(data){
    streamlen = streamlen + data.length;
})
.on('end',function(){
   console.log("Downloaded stream length is: " + streamlen);
})

//This should output your actual size of the mp4 file

检查身体的长度

request.get('http://url.tld/video.mp4', function(err, res, body){
    console.log("The body length of the response in utf8 is: " + Buffer.from(body).length);
    console.log("The body length of the response in ascii is: " + Buffer.from(body,'ascii').length);
});

//This would be approximately double in utf8 and a little less than original bytes in ascii

注意:

管道不是正确的编码,而是管道不进行编码。它只是按原样传递流。

答案 1 :(得分:0)

问题是通过获得如下响应,body类型是UTF-8字符串编码而不是缓冲区。

request.get('http://url.tld/video.mp4', function(err, res, body){
        fs.writeFileSync('./video.mp4', body)
    });

根据请求库文档:

  

encoding - 要在响应数据的setEncoding上使用的编码。如果   null,body作为Buffer返回。别的什么(包括   默认值undefined)将作为encoding参数传递   to toString()(意思是默认情况下这实际上是utf8)。 (注意:如果   你期望二进制数据,你应该设置encoding:null。)

解决方案是通过编码'请求中的options对象的参数如下:

request.get('http://url.tld/video.mp4', {encoding: null}, function(err, res, body){
    fs.writeFileSync('./video.mp4', body)
});