【问题标题】:Node.js - createWriteStream is writing a different file than writeFileNode.js - createWriteStream 正在写入与 writeFile 不同的文件
【发布时间】:2017-01-23 00:32:14
【问题描述】:

我正在尝试使用 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)
});

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

【问题讨论】:

    标签: node.js stream


    【解决方案1】:

    是的,它是编码。在写入文件而不是通过管道传输到流时,主体流在写入文件之前会转换为具有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
    

    注意:

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

    【讨论】:

    • 似乎问题出在响应正文类型上。它是一个字符串而不是缓冲区。
    • 是的。但是除非我以相反的方式调试,否则我无法弄清楚。通过矛盾来证明比阅读整个request库更容易:)
    【解决方案2】:

    问题是通过得到如下响应,body 类型是 UTF-8 String Encoded 而不是 Buffer。

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

    根据请求库文档:

    encoding - 用于响应数据的 setEncoding 的编码。如果 null,主体作为缓冲区返回。其他任何东西(包括 undefined 的默认值)将作为编码参数传递 toString() (这意味着默认情况下这实际上是 utf8)。 (注:如果 你期望二进制数据,你应该设置编码:null。)

    解决方案是将“编码”参数传递给请求中的选项对象,如下所示:

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

    【讨论】:

      猜你喜欢
      • 2012-12-19
      • 2013-10-17
      • 2014-01-09
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      • 2020-06-30
      • 1970-01-01
      • 2019-07-13
      相关资源
      最近更新 更多