如何异步使用javascript下载文件?

时间:2014-03-29 16:29:27

标签: javascript asynchronous google-chrome-extension

我正在构建Chrome扩展程序以从网站下载一系列文件。下载功能源自How to save a file from a URL with JavaScript

程序结构如下:

function download()
{
  while(there're still files to download)
  {
    saveFile(url);
  }
}

但我发现在download()返回后,所有文件实际上都会立即写入磁盘。从Chrome的下载管理器进行检查时,这些文件的地址以blob:开头。

我想知道是否异步调用saveFile,这些文件可以一次写入一个。

1 个答案:

答案 0 :(得分:3)

使用开箱即用的Chrome中的promises,您可以定义如下函数:

// Download a file form a url.
function saveFile(url) {
  return new Promise(function(resolve, reject) {
    // Get file name from url.
    var filename = url.substring(url.lastIndexOf("/") + 1).split("?")[0];
    var xhr = new XMLHttpRequest();
    xhr.responseType = 'blob';
    xhr.onload = function() {
      resolve(xhr);
    };
    xhr.onerror = reject;
    xhr.open('GET', url);
    xhr.send();
  }).then(function(xhr) {
    var a = document.createElement('a');
    a.href = window.URL.createObjectURL(xhr.response); // xhr.response is a blob
    a.download = filename; // Set the file name.
    a.style.display = 'none';
    document.body.appendChild(a);
    a.click();
    return xhr;
  });
}

function download(urls) {
  return Promise.all(urls.map(saveFile));
}

使用它:

download.then(function() {
  alert("all files downloaded");
}).catch(function(e) {
  alert("something went wrong: " + e);
});

如果您想在继续下一步之前等待1个文件下载,则下载功能应该写成:

function download(urls) {
  var cur = Promise.resolve();
  urls.forEach(function(url) {
    cur = cur.then(function() {
      return saveFile(url);
    });
  });
  return cur;
}

用法与以前相同。