zoukankan      html  css  js  c++  java
  • Axios发送请求下载文件(重写二进制流文件)

    用axios正常发送请求下载excel会出现以下问题,即将二级制流文件下载到了本地,下附解决办法:

     一、实现思路:

    这类方法思路如下:

    1. 使用js在页面常见a标签

    2. 创建Blob对象, 在Blob中传入后端返回的response.data

       这一步中Blob需要的是一个数组类型的参数, 后端二进制流这边接收到的response.data使用查看发现是String, 所以我把response.data放进一个长度1的数组, 再传入Blob对象,

       此外需要规定文件类型, 可以是doc的(这里传的word文档)application/vnd.openxmlformats-officedocument.wordprocessingml.document, 也可以是二进制流的application/actet-stream

    3. 创建下载链接 window.URL.createObjectURLblob()

    4. 把3创建的链接变量赋值个a标签的href属性(这类用法详见a标签文档)

    5. 使用document.body.appendChild把a标签挂上去, 再调用a标签的.click()事件

    6. document.body.removeChild(a标签) 移除a标签

    7.window.URL.revokeObjectUR()下载链接)释放blob对象

    二、get请求下载流文件:

    1、使用 responseType: 'blob' 下载文件

    第一步:让后端将下载的接口的response header设置:

    Content-disposition: attachment; filename=数据报表.xlsx(表示会直接下载文件,文件名为‘数据报表’)

    Content-Type:application/octet-stream  (二进制流数据,如常见的文件下载)

    第二步:修改axios请求的responseType为blob,以get请求为例:

    第三步:请求成功,拿到response后,调用下载函数

      //get下载
      onFileDownload = (index,item) => {
        request.get('/file/records/download', {
          params: {
            //这里是参数
          },
          responseType: 'blob',//响应类型为流
          onDownloadProgress:(ProgressEvent) => {//用来计算下载量(实际项目中可以用来显示下载进度)
            let total = item.fileLength;
            // console.log(ProgressEvent);
            let load = ProgressEvent.loaded;
            // console.log(load);
          }
        }).then((resp:any) => {
          if(resp) {
            let blob = new Blob([resp]);
            let url = window.URL.createObjectURL(blob);
            let link = document.createElement('a');
            link.href = url
            link.download = item.fileName || '下载文件';//下载后文件名
            document.body.appendChild(link);
            link.click();//点击下载
            link.remove();//下载完成移除元素
            window.URL.revokeObjectURL(link.href); //用完之后使用URL.revokeObjectURL()释放;
          }else {
            Message.error('文件下载失败,请重试!');
          }
        }).catch(e => {
          Message.error('暂无下载该文件的权限!');
        }).finally(() => {
          //请求结束回调
        })
      }

     或

    download(){
      this.$http({
        method:"get",
        url:接口地址+"?data="+encodeURI(JSON.stringify(data)),
        responseType:'blob'
        }).then((res)=>{
          //这里res.data是返回的blob对象
          var blob = new Blob([res.data], {type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=utf-8'}); //application/vnd.openxmlformats-officedocument.wordprocessingml.document这里表示doc类型
            var contentDisposition = res.headers['content-disposition'];  //从response的headers中获取filename, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 设置的文件名;
          var patt = new RegExp("filename=([^;]+\.[^\.;]+);*");
          var result = patt.exec(contentDisposition);
          var filename = result[1];
          var downloadElement = document.createElement('a');
          var href = window.URL.createObjectURL(blob); //创建下载的链接
          downloadElement.style.display = 'none';
          downloadElement.href = href;
          downloadElement.download =filename ; //下载后文件名
          document.body.appendChild(downloadElement);
          downloadElement.click(); //点击下载
          document.body.removeChild(downloadElement); //下载完成移除元素
          window.URL.revokeObjectURL(href); //释放掉blob对象
        })
    }

    三、post请求下载流文件:

    第一步:让后端将下载的接口的response header设置:

    Content-disposition: attachment; filename=数据报表.xlsx(表示会直接下载文件,文件名为‘数据报表’)

    Content-Type:application/octet-stream  (二进制流数据,如常见的文件下载)

    第二步:修改axios请求的responseType为blob,以post请求为例:

    第三步:请求成功,拿到response后,调用下载函数

    //文件下载
      onFileDownLoad(){
        request.post('/talent/demand/export',{
            //下载参数
          },
          {
            responseType: "blob"//指定响应类型
          }
        ).then((data:any) => {
          if(data) {
            if (!data) {
                return
            }
            let userInfo = this.getLoginNo()
            let url = window.URL.createObjectURL(new Blob([data]))
            let link = document.createElement('a')
            link.style.display = 'none'//设置隐藏创建的标签
            link.href = url
            link.setAttribute('download', `下载文件-${(new Date()).valueOf()}-${userInfo['empName']}(${userInfo['empId']}).xlsx`)//下载文件名称
            document.body.appendChild(link)
            link.click()//点击下载
            link.remove();//下载后移除
            window.URL.revokeObjectURL(link.href); //用完之后使用URL.revokeObjectURL()释放;
          }else {
            Message.error('下载出错,请重试!');
          }
        }).catch(e => {
          Message.error('暂无下载该文件的权限!');
        })
      }

     或

    download(){
      this.$http({
        method:"post",
        url: 接口url,
        data:JSON.stringify(data),
        responseType:'blob',
        headers: {
          'Content-Type': 'application/json;charset=UTF-8'    //后端ssm框架接收json类型
        }
      }).then((res)=>{
      //这里res.data是返回的blob对象
      var blob = new Blob([res.data], {type: 'application/actet-stream;charset=utf-8'});
      var contentDisposition = res.headers['content-disposition'];  //从response的headers中获取filename, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 设置的文件名;
      var patt = new RegExp("filename=([^;]+\.[^\.;]+);*");
      var result = patt.exec(contentDisposition);
      var filename = result[1];
      var downloadElement = document.createElement('a');
      var href = window.URL.createObjectURL(blob); //创建下载的链接
      downloadElement.style.display = 'none';
      downloadElement.href = href;
      downloadElement.download =filename ; //下载后文件名
      document.body.appendChild(downloadElement);
      downloadElement.click(); //点击下载
      document.body.removeChild(downloadElement); //下载完成移除元素
      window.URL.revokeObjectURL(href); //释放掉blob对象
      })
    }

    四、其他下载方法:

    1、下载时创建a标签;

    let formElement = document.createElement('form'); 
    formElement.style.display = "display:none;"; 
    formElement.method = 'post'; 
    formElement.action = ${apiBasePath}/api/xxxxx/downloadDetailData; 
    formElement.target = 'callBackTarget'; 
    let inputElement = document.createElement('input'); 
    inputElement.type = 'hidden'; 
    inputElement.name = "params" ; 
    inputElement.value = params; 
    formElement.appendChild(inputElement); 
    document.body.appendChild(formElement); 
    formElement.submit(); 
    document.body.removeChild(formElement);

    缺点:该种方式下载传给后端的参数类型为:"application/x-www-form-urlencoded",且不支持修改传参类型。

    2、get请求简单下载:

      //get拼接下载
      tableDataExport(){
        const data = {
          ...this.state.params,
          orderType: this.state.orderType,
          pageSize: undefined,
          pageNo: undefined,
          sortBy: undefined,
        }
        let loadData:any = ''
        for (let item in data){
          if(item && data[item]){
            if(isNaN(Number(data[item]))){
              loadData += item + '=' + data[item] + '&'
            }else{
              loadData += item + '=' + Number(data[item]) + '&'
            }
          }
        }
        window.location.href = config.baseURL + '/api/xxxx?' + loadData
      }

    3、浏览器get下载使用window.open下载

    var downURL = '下载接口'  
    
    var getData = '?starTime=20180922&endTime=20180925'
    
    var request = downURL+getData
    
    window.open(request)
  • 相关阅读:
    上线服务器参数调整
    java类加载过程,了解一下?
    利用jvm监控工具,了解一下?
    Druid 监控,了解一下?
    Linux安装mysql,了解一下?
    七大经典排序算法,了解一下?
    HashMap实现原理,了解一下?
    Linux下安装zookeeper和redis,了解一下?
    Linux下安装JDK和Tomcat,了解一下?
    ORACLE-dmp文件导出导入,了解一下?
  • 原文地址:https://www.cnblogs.com/art-poet/p/13730640.html
Copyright © 2011-2022 走看看