关于跨域资源下载

118 阅读2分钟

这篇文章的产生源于某一天,产品给我提了一个优化问题~ 刚看到这个问题我也挺懵的,难道下载不是点击下载按钮,浏览器下方出现下载进度,静静的等待进度条拉满就好吗?

但是在我们的项目里,下载大文件时(上百兆的这种),会发现点击下载没有任何反应,然后突然看到一个已经拉满的进度条,下载完了。

我也挺好奇为什么这样,因为代码不是我写的,直到我看到了代码

   .fetch
      *****资源请求地址******,
      { method: 'PUT' }
    )
    .then(responseData => {
      window
        .fetch(responseData.url, { cache: 'no-cache' })
        .then(res => res.blob())
        .then(responseBlob => {
          const a = document.createElementNS(
            'http://www.w3.org/1999/xhtml',
            'a'
          ) as HTMLAnchorElement;
          a.href = URL.createObjectURL(responseBlob);
          a.download = fileName;
          a.click();
        });

我在想为什么不用最简单的方式下载,就像这样: <a id="a" download="4.png" href="">点我下载</a> 尝试之后果然是我片面了,并没有下载而是在新页面预览了😳 ,没错当时我就是这个表情。我们的资源是放在亚马逊云上的,跨域了啊。难怪前面的同学没有用这么简单的方式,年轻人👱 还是要谦虚呀,我能想到的别人怎么会想不到!

所以还是要找别的办法吧,既然是跨域问题,那就解决跨域问题呗,用什么解决呢,比较常见的iframe先试试咯:

 // 下载资源
  public downloadResource = (fileName: string, uuid: string) => {
    alo7Api
      .fetch(`********`,
        { method: 'PUT' }
      )
      .then(responseData => {
        window.fetch(responseData.url, { cache: 'no-cache' }).then(res => {
          const { url } = res;
          resouseDownloadHelper(url, fileName);
        });
      })
      .catch(error => message.error('下载失败:' + error.message));
  };

export function resouseDownloadHelper(url: string, fileName: string) {
  if (document.getElementById('iframe')) {
    document.body.removeChild(document.getElementById('iframe'));
  }
  const iframe = document.createElement('iframe');
  iframe.style.display = 'none';
  iframe.id = 'iframe';
  iframe.setAttribute(
    'src',
    'https://s3.cn-north-1.amazonaws.com.cn/**********/download.html'
  );
  document.body.appendChild(iframe);
  iframe.onload = () => {
    iframe.contentWindow.postMessage(
      {
        url,
        fileName,
      },
      '*'
    );
  };
}

在网页上放一个看不到的download.html,把这个页面也存在亚马逊云上,跨域问题完美规避掉了,下载进度也正常显示。

如果恰好解决了你的问题,帮忙点个赞👍 ~ 初入行小白,评论区欢迎各位大佬指点~