如何使用 fetch API 在 javascript 中下载具有多个块的单个文件

How to download single file with multiple chunks in javascript using fetch API

我在我的 React 应用程序中使用 fetch API 从 URL 下载文件。每个 URL 提供一个块作为响应。当文件只有一个块时,我可以使用 response.blob() 来下载文件。但是,如果单个文件有多个块,我必须从 n 个不同的 urls 中获取块,比如 url1,url2,..等等。我如何结合他们的响应来生成单个 blob 并下载文件。

下面是下载只有一个块的文件的代码(从url-1中获取)。

let downloadUrl = `https://url-1`;
      fetch(downloadUrl, {
        method: 'GET'
      })
        .then(
          (res: any) => {
            if (res.ok && res.status === 200) {
              //File response loaded
            } else {
              return null;
            }
            return res.blob();
          },
          error => {
            // error in downloading
          }
        )
        .then(fileData => {
          if (fileData) {
            let url = window.URL.createObjectURL(fileData);
            let a = document.createElement('a');
            a.href = url;
            a.download = file.fileName;
            a.click();
          }
        });

我可以在 fetch API 中发出多个请求并使用 Promise.all(responseArr)。但是如何将他们的响应组合成单个 blob 响应?

您可以通过 fetch() and then get each response as an array buffer with .arrayBuffer() 获取单个块。

然后您可以使用 Blob(array, options) 构造函数创建一个新的 blob,其中包含您刚刚下载的所有数组缓冲区。

示例:

// fetch chunks from somewhere
let urls = ["http://foo.bar/chunk/1", "http://foo.bar/chunk/2"];
let chunkPromises = urls.map(url => {
  return fetch(url).then(res => {
    return res.arrayBuffer();
  });
});

Promise.all(chunkPromises).then(chunks => {
  // combine chunks into a single blob
  let blob = new Blob(chunks, {
    // Optional: specify the MIME Type of your file here
    type: "text/plain" 
  });

  // download the blob
  let url = window.URL.createObjectURL(blob);
  let a = document.createElement('a');
  a.href = url;
  a.download = "Filename.txt";
  a.click();
});

我会遍历 URL 以按顺序下载块并在下载时组合它们

try{
    var urls = ['https://url-1','https://url-2.0','https://url-3.1415']
    var fullFile = new Blob();
    for (let x = 0; x < urls.length; x++){
        await fetch(urls[x]).then((res) => {
            if (!res.ok || res.status !== 200) {
                throw('Download failed');
            }
            return res.blob();
        }).then(data => fullFile = new Blob([fullFile, data]));
    }
    let url = window.URL.createObjectURL(fullFile);
    let a = document.createElement('a');
    a.href = url;
    a.download = file.fileName;
    a.click();
} 
catch(e){console.log(e)};