js下载文件的实现方式有哪些?

目录
文章目录隐藏
  1. 1. 普通下载
  2. 2. 流文件下载

1. 普通下载

当后端返回的资源是链接时,此时可以使用 a 标签或者 window.location.href直接打开。

1.1 a 标签形式

在 H5 中,a标签新增了download 属性,包含该属性的链接被点击时,浏览器会以下载文件方式下载 href 属性上的链接。

 <a rel="nofollow" href="https://mybj123.com/links?url=aHR0cHM6Ly94eHguIGNvbQ==" download="example.html">下载</a>

// 或者封装
function download(href, title) {
    const a = document.createElement('a');
    a.setAttribute('href', href);
    a.setAttribute('download', title);
    a.click();
}
download('https://xxx. com', 'test')

1.2 window.location.href 直接打开

window.location.href === 'https://xxx. com'

2. 流文件下载

当后端返回的文件是流文件时,以 umi-request 请求方法为例

首先应在请求中设置返回类型:responseType: "blob"

import request from "umi-request";

export const downLoad = (url, fileName) =>
  request(url, {
    method: "POST",
    data: data,
    responseType: "blob", // 代表内存之中的一段为二进制
  }).then(data) => {
    const blob = data;
    let link = document.createElement("a");
    link.href = URL.createObjectURL( new Blob([blob], { type: "application/vnd.ms-excel" }) );
    link.download = fileName;
    document.body.appendChild(link);
    link.click();
    URL.revokeObjectURL(link.href);
};

2.1 自定义文件名

此时可以发现后端返回的是流文件,前端接到的是乱码。当前端自定义文件名时,可以直接下载

downLoad('https://xxx. com/api/download', 'test.xlsx')

2.1 采用后端定义的文件名

当采用后端的fileName时,此时要获取后端在 content-disposition 中定义的文件名。

首先调用接口,发现文件名是在请求头content-disposition 中,需要注意的是:虽然我们能看到,但是却拿不到请求头。

如果想让浏览器能访问到其他响应头的话,需要后端在服务器上设置 Access-Control-Expose-Headers

// 后端面大致写法
headers.add("Access-Control-Expose-Headers", "Content-Disposition");

此时可以拿到相关信息,发现是编码的,需要 decodeURI 进行解码:

const disposition = response.headers.get('Content-Disposition');

const fileName = decodeURI(disposition.split(";")[1].split("filename=")[1])

注:直接在请求方法里是不能获取到请求头信息的,需要对请求进行拦截

request.interceptors.response.use(async (response) => {
  const disposition = response.headers.get("Content-Disposition"); // 获取 Content-Disposition
  return disposition // 当 Content-Disposition 中有值的时候进行处理,其他请求的响应则放过
    ? {
        blob: await response.blob(), // 将二进制的数据转为 blob 对象,这一步是异步的因此使用 async/await
        fileName: decodeURI(disposition.split(";")[1].split("filename=")[1]), // 处理 Content-Disposition,获取 header 中的文件名
      }
    : response;
});

完整的代码

request 文件:

import request from "umi-request";

// 响应拦截
request.interceptors.response.use(async (response) => {
  const disposition = response.headers.get("Content-Disposition"); // 获取 Content-Disposition
  return disposition // 当 Content-Disposition 中有值的时候进行处理,其他请求的响应则放过
    ? {
        blob: await response.blob(), // 将二进制的数据转为 blob 对象,这一步是异步的因此使用 async/await
        fileName: decodeURI(disposition.split(";")[1].split("filename=")[1]), // 处理 Content-Disposition,获取 header 中的文件名
      }
    : response;
});

export const downLoadExcel = (url) =>
  request(url, {
    method: "POST",
    data: data,
    // responseType: "blob", // 注释掉这一段
  }).then(data => {
    const { blob, fileName } = response;
    let link = document.createElement("a");
    link.href = URL.createObjectURL( new Blob([blob], { type: "application/vnd.ms-excel" }) );
    link.download = fileName;
    document.body.appendChild(link);
    link.click();
    URL.revokeObjectURL(link.href);
    document.body.removeChild(link);
});

react 文件:

<Buttton onClick={download}> 下载 </Button>

js 文件:

async download() {
   await downLoadExcel('http://xxx. com/api/download');
},

以上内容为自己平时遇到的问题记录,供参考,如果能帮到你那再好不过了。

「点点赞赏,手留余香」

0

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
码云笔记 » js下载文件的实现方式有哪些?

发表回复