前端获取二进制流下载文件

背景介绍:前端请求获取二进制流数据后由前端转化为excel文件,并通过获取响应头response Header里的Content-Disposition属性获取文件名,最终实现下载excel文件的功能。

实现方式:

一、通过axios库实现
二、原生ajax请求

一、axios请求实现

主要代码:

                import axios from 'axios'
                //设置返回数据的格式为二进制流,可选值为  arraybuffer,blob,document,json,text,stream,默认值为json
                //注意:此时后端返回的数据只能包含二进制流,若包含其他信息如文件名等,也会被当成二进制流处理导致文件乱码。
                axios.post(this.$globalConf.atapPathPrefix + '/system/indicator/export', { postParams }, { responseType: 'blob' }).then(res => {
                    console.log(res)
                      //这里res.data是返回的blob对象,即对应的二进制流
                      let blob = new Blob([res.data]);
                    let downloadElement = document.createElement('a');
                      let href = window.URL.createObjectURL(blob); //创建下载的链接
                    let fileName = res.headers["content-disposition"].split(';')[1].split('=')[1]
                    downloadElement.href = href;
                    downloadElement.download = decodeURIComponent(fileName)//解码
                    document.body.appendChild(downloadElement);
                    downloadElement.click();
                      document.body.removeChild(downloadElement);
                      window.URL.revokeObjectURL(href); //释放掉blob对象
                })
               

返回的res结果

前端获取二进制流下载文件_第1张图片
image.png

可能出现的问题:
无法获取headers的content-disposition字段

解决办法:
在服务端设置header:

Access-Control-Expose-Headers: Content-Disposition

(3)Access-Control-Expose-Headers
该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。

摘自阮一峰-跨域资源共享 CORS 详解

二、原生ajax请求
function downloadCase (id) {    //原生ajax实现
    var url = basePath+"/record/downloadCase.ajax?caseId="+id;
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.responseType = "blob";    // 指定返回类型blob
    xhr.onload = function () {
        if (this.status === 200) {
            var blob = this.response;
            var reader = new FileReader();
            reader.readAsDataURL(blob);    // 转换为base64
            reader.onload = function (e) {
                //console.log(xhr.getAllResponseHeaders());//获取所有的响应头消息
                //console.log(xhr.getResponseHeader('content-disposition'));//获取某一个响应头消息
                let fileName = '';
                if(xhr.getResponseHeader('content-disposition')){
                    fileName = xhr.getResponseHeader('content-disposition').split(";")[1].split("=")[1];
                }else{
                    layer.msg('下载用例出错!');
                    return;
                }
                let browserType = getBrowserType();
                let a = document.createElement('a');
                //注意:在火狐浏览器下中文名解析出错,这里针对Firefox文件名做base64解码处理
                if(browserType === 'FF'){//firefox
                    a.download = base64_decode(fileName); // base64解码
                }else{
                    a.download = decodeURIComponent(fileName);
                }
                a.href = e.target.result;
                console.log(e.target.result);
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a); //下载完成移除元素
            }
        }
    };
    xhr.send();
}

//获取浏览器类型
function getBrowserType () {
    var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
    var isOpera = userAgent.indexOf("Opera") > -1;
    //判断是否Opera浏览器
    if (isOpera) {
        return "Opera"
    }; 
    //判断是否Firefox浏览器
    if (userAgent.indexOf("Firefox") > -1) {
        return "FF";
    } 
    //判断是否chorme浏览器
    if (userAgent.indexOf("Chrome") > -1){
        return "Chrome";
    }
    //判断是否Safari浏览器
    if (userAgent.indexOf("Safari") > -1) {
        return "Safari";
    } 
    //判断是否IE浏览器
    if (userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1 && !isOpera) {
        return "IE";
    }
    //判断是否Edge浏览器
    if (userAgent.indexOf("Trident") > -1) {
        return "Edge";
    };
}

//base64解密 需要引入CryptoJS
function base64_decode(code){
    var words = CryptoJS.enc.Base64.parse(code);
    return words.toString(CryptoJS.enc.Utf8)
}


以上,如有错误欢迎指正,如果喜欢还请点个赞再走,谢谢!更多项目实战源码请移步我的码云地址

你可能感兴趣的:(前端获取二进制流下载文件)