浏览器正在取消多个文件下载请求

问题描述 投票:0回答:3

我正在尝试下载用户选择下载的多个文件。但是,浏览器正在取消除最后一次下载请求之外的所有下载请求。如果我将请求之间的延迟增加到大约 1 秒,那么这些文件就会被下载,但即使在这种情况下,有时也会丢失一些文件。这些文件是从亚马逊 s3 url 下载的(即这些是 CORS)。

我通过使用 url 创建一个锚元素,然后使用 javascript 调用其上的单击事件来完成此操作。

downloadFile(url) {
    let a = document.createElement('a');
    a.id = url;
    // a.setAttribute('target', 'blank');
    a.download = '';
    a.href = url;
    // firefox doesn't support `a.click()`...
    // console.log('dowmloading ' + url);
    a.dispatchEvent(new MouseEvent('click'));
    a.remove();
}

然后在下载按钮单击事件上我正在这样做:

let delay = 0;
        urlList.forEach(url => {
            return setTimeout(downloadFile.bind(null, url), 100 * ++delay);
        });

有办法做到这一点吗?

为什么浏览器取消请求?

javascript browser download
3个回答
7
投票

为什么浏览器取消请求?

因为在浏览器完全完成您单击上一个链接时必须执行的操作之前,您实际上是通过单击下一个链接来“取消导航”。

如果这不是下载,而是页面的常规链接,那么这就是您想要的行为 - 如果用户首先单击页面 A 的链接,但随后失去耐心并单击页面 B 的另一个链接,那么此时对页面 A 的请求被取消 - 无需加载两个资源,因为无论如何只能同时显示一个资源。

如果您不想找出一个超时的“神奇数字”以某种方式使其“起作用”,我认为您对此无能为力 - 特别是因为您不知道这是否适用于一般,或者可能只是在您的机器上,通过您的互联网连接等。

我正在尝试下载用户选择下载的多个文件。

您可以将这些选定的文件动态地封装到服务器上的容器格式中 - 例如 ZIP(严格来说,不仅仅是一个“容器”),这样用户只需下载一个文件(其中然后他们将不得不在自己的机器上再次打开包装。)

或者您首先更改文件选择过程。与其让用户使用复选框或类似的东西标记他们想要的文件,不如向他们提供指向文件的直接链接?然后他们可以依次单击他们想要的每一个,然后就会发生“正常”下载功能。


2
投票

@misorude 关于他们被取消的原因是正确的,但解决方法是使用

iframe
而不是锚标记来下载文件。

下面是下载文件的打字稿实现:

export function downloadFile(downloadLink: string): void {
  const iframe = document.createElement("iframe");
  iframe.setAttribute("sandbox", "allow-downloads allow-scripts");
  iframe.src = downloadLink;
  iframe.setAttribute("style", "display: none");

  document.body.appendChild(iframe);
}

所以它与你的实现类似 - 唯一的事情是,你的 DOM 上会有杂散(未显示)的 iframe。无法判断 iframe 何时完成下载文件,因此没有足够的方法知道何时删除它们。但至少你不会让你的网络请求被取消。


0
投票

你也可以像这样使用 fetch 和 blob

    void fetch(downloadLink)
      .then(response => response.blob())
      .then(blob => {
        const blobUrl = window.URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.style.display = 'none';
        open && link.setAttribute('target', '_blank');
        link.setAttribute('download', filename);
        link.setAttribute('href', blobUrl);
        link.click();
        URL.revokeObjectURL(blobUrl);
        setLoadingDownloadItem(prev => prev.filter(item => item !== index));
      });
  };

© www.soinside.com 2019 - 2024. All rights reserved.