怎么完全模拟异步下载模拟a标签?(弹框时机一样)

如题,我用a标签请求下载和异步请求下载,明显弹出保存窗口的速度a标签的快,我这边是秒弹窗。而后者是等待整个文件下载完之后再弹窗,因为是响应后再用blob模拟a标签下载。两者调的是同一个api。用的是vue,异步请求axios。


普通a标签:

const a = document.createElement('a');
    a.href = `${Config.fileBaseURL}/download?url=${url}&fileName=${fileName}`;
    a.download = fileName;
    a.click();

异步:

api.get(`/download?url=${url}&fileName=${fileName}`)
    .then(res => {
      const blob = new Blob([res.data], { type: 'application/octet-stream' });
      const a = document.createElement('a');
      const url = window.URL.createObjectURL(blob);
      a.href = url;
      a.download = fileName;
      a.click();
      window.URL.revokeObjectURL(url);
    });

代码如上,请求地址是一样的。
我用fidder抓包的时候,普通的a标签弹窗速度又不是秒弹出了,可能是因为代理.两者速度基本一样.
有大神研究过吗?

阅读 4.7k
3 个回答

在评论里,楼主说想问的其实是“异步下载没有方法可以像它一样下载完前触发弹框吗”。

先说答案,有,但是相当脏,是一种hack。

StreamSaver.js

作者给的示例

原理是滥用Service Worker,魔改fetch拿到的响应,欺骗浏览器,然后再把readableStream直接送入(真正的)硬盘。

这个估计和你的网络情况有关啊。
因为需要收到一些数据后才会弹出保存对话框的。

使用构建form表单来下载吧,可以达到类似的效果,代码如下:

function download(url, params = {}) {
  const token = {
    Authorazation: getToken()
  }
  const FORM = document.createElement('FORM')
  FORM.name = 'form'
  FORM.method = 'POST'
  FORM.action = url

  function appendParams(params) {
    for (const key in params) {
      const INPUT = document.createElement('INPUT')
      INPUT.type = 'HIDDEN'
      INPUT.name = key
      INPUT.value = params[key]
      FORM.appendChild(INPUT)
    }
  }
  params = Object.assign(token, params)
  appendParams(params)
  document.body.appendChild(FORM)
  FORM.submit()
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题