从URL提取Blob并写入文件

时间:2018-07-20 14:35:08

标签: node.js blob fs fetch-api

我正在尝试从服务器fetch提取一些二进制数据(MP3),然后将其存储在文件中:

var fs = require ('fs');
var fetch = require ('node-fetch');

fetch (
   audioUrl,
   {
      method: 'GET',
      headers: { 'Accept': '*/*' }
   }
)
.then ((res) => res.blob())
.then ((blob) => {
    console.log ('Blob size: ', blob.size);

    fs.writeFile (
        `filename.mp3`,
        blob,  // BUG HERE
        (err) => {
            if (err) {
                console.log (`Error writing audio ${audioIdx}`, err);
            }
        }
    );
})

问题被标记为BUG HERE。我正在将blob传递给fs,后者不了解blob,而只是写[object Blob]。我还尝试了以下方法:

blob                                // writes [object Blob]
new Uint8Array (blob)               // writes empty file
Buffer.from (new Uint8Array (blob)) // writes empty file
new Buffer (blob, 'binary')   // Error: argument is not a Buffer

以上所有工作均未完成。如何正确执行此操作?

请注意,我在致电blob.size之前先登录writeFileblob.size显示正确的大小,因此fetch似乎成功。

2 个答案:

答案 0 :(得分:3)

好吧,因此从MDN Docs开始,Blob不是缓冲区,而这是您写入文件系统所需要的。

我认为您最好从响应中获取缓冲区,例如:

.then(res => res.buffer())
.then(/* write your file here */)

尽管取决于文件的大小,最好的选择可能是完全跳过.writeFile函数,而改为管道传输。

答案 1 :(得分:1)

您可以使用fs.createWriteStream将响应流式传输到文件。

fetch(
    audioUrl,
    {
        method: 'GET',
        headers: { 'Accept': '*/*' }
    }
).then(res => {
    new Promise((resolve, reject) => {
        const dest = fs.createWriteStream(`filename.mp3`);
        res.body.pipe(dest);
        res.body.on('end', () => resolve());
        dest.on('error', reject);
    })
});