前端下载的方式总结(url,文件流,压缩包)

1.比较常见的是通过a标签的href属性直接访问文件url地址。

(1)
const downloadUrl = (url: string, file_name?: string) => { if (url) { url = url.replace(/^http/, "https"); const a = document.createElement("a"); a.href = url + `?attname=${file_name || "doc"}`; a.download = file_name || "doc"; a.click(); } };
(2)
attname参数值需要带扩展名,要不然识别不了文件类型。这种方式下载一些不用验证的资源是可以,
但如果下载接口需要验证,需要你在请求头带token,这种方式就行不通了(可以看到浏览器下载进度)
  <a href="文件url?attname=filename.jpg">xxx</a>(可以看到浏览器下载进度)
 <a href="http://www.baidu.com" download="baidu.html">下载</a>(无法看到浏览器下载进度)

2、window.open

window.open('http://www.baidu.com', '_blank', 'download=baidu.html')

当然这种方式也是有缺陷的,对比于a标签,这种方式不能下载.html.htm.xml.xhtml等文件,因为这些文件会被当成html文件来处理,所以会直接在当前页面打开。

同样也不能下载跨域的文件,毕竟是window.open,不是window.downloadwindow.download是假想)。

3、文件流下载,通过接口下载

 * @Description:
        参数注释: (fileName: string, url: string, exportDate?: boolean)
        fileName: 下载文件名
        url: 文件地址
        exportDate: 是否是导出文件流
 *
export default function (fileName?: string, url?: string, exportDate?: boolean) {
  if (!url) {
    ElMessage({
      type: "warning",
      message: "下载地址为空,无法下载"
    });
    return;
  }
  url = url.replace(/http:/, "");
  const x = new XMLHttpRequest();
  x.open("GET", url, true);
  if (exportDate) {
    const session = getSession("user", true) as USER;  // 你的token
    if (session) {
      x.setRequestHeader("Authorization", `Bearer ${session.token}`);
    }
  }

  x.responseType = "blob";

  x.onload = function () {
    let xlsxName = null;
    if (exportDate) {
      xlsxName = fileNameHeader(x.getResponseHeader("Content-Disposition"));
    }
    const url = window.URL.createObjectURL(x.response);
    const a = document.createElement("a");
    a.href = url;
    if (exportDate) {
      a.download = xlsxName || "file";
    } else {
      a.download = fileName || "file";
    }

    a.click();
  };
  x.send();
}

function fileNameHeader(d: any) {
  let result = null;
  if (d && /filename=.*/gi.test(d)) {
    result = d.match(/filename=.*/gi);
    return decodeURI(result[0].split("=")[1]);
  }
}

4、批量下载生产压缩包

import axios from "axios";
import JSZip from "jszip";
import FileSaver from "file-saver";

const getFile = (url: string) => {
  return new Promise((resolve, reject) => {
    axios({
      method: "get",
      url,
      responseType: "arraybuffer"
    })
      .then((data) => {
        resolve(data.data);
      })
      .catch((error) => {
        reject(error.toString());
      });
  });
};

export default function batchDownload(urlArr: any, name?: string, arrChildName?: string[]) {
  const data: string[] = urlArr; // 需要下载打包的路径, 可以是本地相对路径, 也可以是跨域的全路径
  const zip = new JSZip();
  const cache: any = {};
  const promises: string[] = [];
  data.forEach((item, index) => {
    const promise: any = getFile(item).then((data: any) => {
      // 下载文件, 并存成ArrayBuffer对象
      const arr_name = item.split("/");
      let file_name = arr_name[arr_name.length - 1]; // 获取文件名
      if (arrChildName && arrChildName.length) {
        file_name = arrChildName[index];
      }
      zip.file(file_name, data, { binary: true }); // 逐个添加文件
      cache[file_name] = data;
    });
    promises.push(promise);
  });

  Promise.all(promises).then(() => {
    zip.generateAsync({ type: "blob" }).then((content) => {
      // 生成二进制流
      FileSaver.saveAs(content, name || "打包下载.zip"); // 利用file-saver保存文件
    });
  });
}

 

posted @ 2022-08-18 12:22  府谷市民小柴  阅读(1781)  评论(0编辑  收藏  举报