前端实现流文件下载、导出功能解决方案

一、自定义下载文件名称

1、封装下载方法(可以通过挂载在vue实例上成为全局函数)

import requset from 'axios'
// 经过请求拦截器、响应拦截器处理
onloadFileName(url,method,params,fileName){
	request({
		url:url,
		method:method,
		// get 方法传参为例
		data:{
		...params
		},
		// 添加响应数据类型
		responseType: 'blob',
		// 添加文件下载特定请求头
	    headers: {
	       'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
	     },
	}).then(res =>{
		// res 为响应拦截器返回的内容,大家可以对比自己的响应拦截器修改下面方法的判断
		if (!data) {
	     this.$message.warning("文件下载失败");
	      return;
	    }
	    // web Api种操作流文件的方法
	     if (typeof window.navigator.msSaveBlob !== "undefined") {
	     // msSaveBlob:只提供一个保存按钮
	     // window.navigator.msSaveBlob(new Blob([data]),`${fileName}.txt`);
	     
	     // msSaveOrOpenBlob:提供保存和打开按钮	
	     //window.navigator.msSaveOrOpenBlob(newBlob([data]),`${fileName}.txt`);
		     window.navigator.msSaveBlob(
		        new Blob([data]),
		        filename + ".xls"
		      );
	    } else {
	    // 自定义实现流文件下载
		      let url = window.URL.createObjectURL(new Blob([data]));
		      let link = document.createElement("a");
		      link.style.display = "none";
		      link.href = url;
		      link.setAttribute("download", fileName + ".xls");
		      document.body.appendChild(link);
		      link.click();
		      document.body.removeChild(link); //下载完成移除元素
		      window.URL.revokeObjectURL(url); //释放掉blob对象
	    }
	})
}

t经过响应拦截器后返回的有效数据,所以直接使用new Blob([data])
2、调用下载方法

this.onloadFileName('xxx/xxx/xx','get',{id:'xxxxxxx'},'文件一')

二、文件名称从后端响应头数据中获取

相应拦截器处理之前的数据,文件名在content-disposition字段中存放
·1、处理响应拦截器返回的数据,将文件名暴露暴露出去

// 设置请求接受拦截器 响应拦截器中兼容处理流数据
serves.interceptors.response.use(response => {
	  // 设置接受数据之后,做什么处理
    const res = response.data
     if (!res.code && res.code === 200) {
     // 数据是流
        if(response.headers['content-disposition']){
            return {
                blobData:res,
                contentDisposition:response.headers['content-disposition']
            }
        }
        // 正常情况下
        else{
            return res
        }
       
    }
})

相应拦截器过滤后的数据描述
2、封装下载方法

onloadFileName(url,method,params){
	request({
		url:url,
		method:method,
		// get 方法传参为例
		data:{
		...params
		},
		// 添加响应数据类型
		responseType: 'blob',
		// 添加文件下载特定请求头
	    headers: {
	       'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
	     },
	}).then(res =>{
		 if (!res.blobData) {
            this.$message.warning("文件下载失败");
              return;
          }
          // web Api种操作流文件的方法
	     if (typeof window.navigator.msSaveBlob !== "undefined") {
		     // msSaveBlob:只提供一个保存按钮
		     // window.navigator.msSaveBlob(new Blob([data]),`${fileName}.txt`);
		     
		     // msSaveOrOpenBlob:提供保存和打开按钮	
		     //window.navigator.msSaveOrOpenBlob(newBlob([data]),`${fileName}.txt`);
             window.navigator.msSaveBlob(
                  new Blob([res.blobData]),
                  res.contentDisposition+ ".xls"
              );
           	} else {
               let url = window.URL.createObjectURL(new Blob([res.blobData],
                   { 
                    type:
                        ".xlsx"
                   } 
                ));
                let link = document.createElement("a");
                link.style.display = "none";
                link.href = url;
                // decodeURIComponent()解码文件名称
                // data.contentDisposition.split('=')[1] 分割文件名称
                const fileName = decodeURIComponent(data.contentDisposition.split('=')[1])
                link.setAttribute("download",fileName);
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link); //下载完成移除元素
                window.URL.revokeObjectURL(url); //释放掉blob对象
          }
}

3、调用下载方法

this.onloadFileName('xxx/xxx/xx','get',{id:'xxxxxxx'})

问题一:后端返回的数据无法解析
在请求函数中添加响应类型以及响应头
在这里插入图片描述
问题二、后端返回的文件名经过相应拦截器后无法暴露出来导致无法获取文件名报错。
后端返回二进制流数据时设置请求头,添加可暴露出的字段

 response.setHeader("Access-Control-Expose-Headers", "Content-Disposition")
 response.setHeader("Content-Disposition", ...)
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值