我正在尝试使用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)
});
为什么会这样?管道功能是否为相应的文件设置了正确的编码?
答案 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)
});