JS文件下载方式及浏览器拦截问题

683 阅读1分钟
一、文件下载的几种方式
1、window.open()
2、创建a标签
function download(url) {
    if(!url) return
    const el = document.createElement('a')
    el.href = url
    el.target = '_blank'
    document.body.appendChild(el)
    el.click()
    document.body.removeChild(el)
}
3、接收的是文件流的情况
function downloadBlob(blobRes, fileName) {
    if(!blobRes) return;
    const blob = new Blob([blobRes]);
    const el = document.createElement('a')
    const url = (window.URL ? window.URL : window.webkitURL).createObjectURL(blob)
    el.href = url
    el.download = fileName
    document.body.appendChild(el)
    el.click()
    document.body.removeChild(el)
}
二、浏览器下载窗口被拦截问题

​ 在浏览器的安全机制里,非用户触发的弹出窗口window.open()会被阻止,会被认为是用户不希望打开的新页面。

​ 在用户触发异步函数内触发下载,超过一定时间也有可能会被拦截。

1、先新增标签页,异步返回之后替换对应的地址
const onDownload = async () => {
    // 这种方式会有一个空白页面,对用户不是很友好
    const newTab = window.open()
    // 可先打开一个加载页面  const newTab = window.open(loadingUrl)
    const url = await api()
    if(url) {
        newTab.location = url;
    }else {
        newTab.close()
    }
}
2、被拦截后,提示用户手动下载

(1)、react hooks

import React from "react";
import { remindCloseWarning } from "../utils/remind";

// 打开下载窗口被拦截后提示手动下载
export const useWindowOpen = () => {
  function windowOpenWithCheck(url) {
    if (!url) return;
    const tab = window.open(url);
    // 被拦截
    if (!tab) {
      const closeWarning = remindCloseWarning("下载弹窗未能正常打开,请手动下载!", {
        operateView: (
          <>
            <a
              href={url}
              target='_blank'
              onClick={() => {
                closeWarning && closeWarning();
              }}
              style={{ marginLeft: "8px", textDecoration: "underline" }}
            >
              点击下载
            </a>
          </>
        ),
      });
    }
  }
  return [windowOpenWithCheck];
};

(2)、使用

const [windowOpenWithCheck] = useWindowOpen();
const onDownload = async () => {
    const url = await api();
    if(url) {
        windowOpenWithCheck(url)
    }
}

(3)、效果

download.jpg