2017-01-22 77 views
0

我試圖使用HTTP GET請求遠程下載MP4文件。當HTTP GET響應正在被寫入文件時,該文件正在寫入完美(〜3MB)。Node.js - createWriteStream寫入的文件不是writeFile

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

然而,當HTTP GET響應身體正在由fs.writeFileSync函數寫的,它創建了一個較大的文件(〜7MB),並且由於它損壞它不能被執行。

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

爲什麼會發生? pipe函數是否爲相應的文件設置了正確的編碼?

回答

0

是的,它是編碼。在寫入文件而不是管道到流時,在寫入文件之前,正文流將被轉換爲緩衝區對象,編碼爲utf8

只是一個簡單的實驗來證明這一點。

檢查下載的流

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 

注:

這並不是說管道不正確編碼,它只是管道不做編碼。它只是傳遞流。

+0

看起來問題是響應主體類型。它是一個字符串而不是緩衝區。 – Avi

+0

是的。但我無法弄清楚,除非我以相反的方式進行調試。通過相互矛盾而不是讀出整個'request'庫來更容易證明:) – user3151330

0

問題是,通過獲得響應如下,body類型是UTF-8字符串編碼而不是緩衝區。

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

根據請求庫的文檔:

編碼 - 編碼要對響應數據的setEncoding使用。如果 爲null,則正文返回爲緩衝區。其他任何東西(包括未定義的默認值 )都將作爲編碼參數 傳遞給toString()(這意味着默認情況下實際上是utf8)。 (注意:如果 你期望的二進制數據,則應該設置編碼:空)

的解決方案將是選項在請求對象傳遞一個「編碼」參數如下:

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