下载二进制文件

今天遇到一个坑,前端带参数向后台发送请求,后台根据参数返回一个文件,这个文件是二进制格式,根据调研得知,最好是使用原生对象XHRHttpRequest来下载文件,避免出现文件解压失败的情况,好了,然后就去网上找相关代码来实现,先贴上一个实验通过的代码.

// A code block
const val={}
const address = `xxx`;
const data = JSON.stringify(val);
const oAjax = new XMLHttpRequest();
    oAjax.responseType = 'blob'
    oAjax.open('POST', address, true);
    oAjax.setRequestHeader("Content-type", "application/json;charset=UTF-8");
    oAjax.onreadystatechange = () =>{
      if (oAjax.readyState === 4 && oAjax.status === 200) {
        const type = oAjax.getResponseHeader('Content-Type')
        const blob = new Blob([oAjax.response], {type})
        const fileName = oAjax.getResponseHeader('Content-Disposition').split('filename=')[1];
        if (typeof window.navigator.msSaveBlob !== 'undefined') {   
          window.navigator.msSaveBlob(blob, fileName)
        } else {
          const URL = window.URL || window.webkitURL
          const objectUrl = URL.createObjectURL(blob)
          if (fileName) {
            const a = document.createElement('a')
            // safari doesn't support this yet
            if (typeof a.download === 'undefined') {
              window.location = objectUrl
            } else {
              a.href = objectUrl
              a.download = fileName
              document.body.appendChild(a)
              a.click()
              a.remove()
            }
          } else {
            window.location = objectUrl
          }
        }
      } 
    };
    oAjax.send(data);

这里说一下几个强调的点:

  1. data = JSON.stringify(val) 参数需要先转换一下格式,要不然后台会报400-格式错误
  2. oAjax.responseType = ‘blob’ 如果后台返回的是一个二进制流,那么就一定要写上这个返回格式,
    response: Blob(11295) {size: 11295, type: “application/octet-stream”}
    responseType: “blob”
    responseURL: “xxx”
    可以看下console.log(oAjax),这里response必须是正确的格式,如果response返回的内容是乱码,那么会导致文件解析出错,文件可能会打不开或者解压出错
  3. 第三点和第二点相关 oAjax.open(‘POST’, address, true); 这一句代码中的第三个参数,必须要写true,不然会导致第二点出错
  4. 第四个点,有点无关紧要,就是以上代码使用的时候必须全部复制,不能只截取部分,不然会出错

参考链接:
https://blog.csdn.net/qq_32247819/article/details/79270788
https://blog.csdn.net/aydongzhiping/article/details/82462473

04/16 更新
有个更方便的方法,这个方法能兼容 ie,火狐,chrome

const  fileName = '文件名.zip';
if (window.navigator.msSaveOrOpenBlob) {
   navigator.msSaveBlob(data, fileName);
} else {
    const a = document.createElement('a');
	const url = URL.createObjectURL(data);
	
	a.href = url;
	document.body.appendChild(a);
	a.download = fileName;
	a.click();
	document.body.removeChild(a);
	URL.revokeObjectURL(url);
}

10/24 更新
有些需要注意的点
在这里插入图片描述
在 Content-disposition 中,可以看到 fileName 是有值的,但是前端是拿不到的,虽然下载后的文件名称一般是由前端定义的,但是下载下来的文件格式,是 zip/xlsx/doc 这个要先了解好在文件名后定义,如果文件类型不对,下载后的文件内容就不对。比如上图 fileName 后面带的文件类型后缀是 xlsx,我一开始写成 文件名.zip下载后的压缩包打开就是下图这样,将后缀改成 xlsx 之后,下载下来的就是一个正确内容的 xlsx 文件

在这里插入图片描述

另外,下载文件还有一个要处理的地方

const contentType = response.headers.get('Content-Type');

if (contentType && contentType.indexOf('json') > -1) {
  return response.json();
} else if (contentType && contentType.indexOf('octet-stream') > -1) {
  return response.blob();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值