zoukankan      html  css  js  c++  java
  • vue 项目中下载数据、导出数据实践(a标签方法、axios方法)

    业务需要导出表格数据,后端返回的是二进制数据流,使用axios请求,在前端接收到的是如下:

    这就是二进制数据流,看不懂不要紧,前端只要处理如何下载就行了,下面就贴一下具体的代码实现。

    axios封装:

    import axios from "axios";
    import { Loading, Message } from "element-ui";
    import store from "@/store";
    // import { getToken } from "@/utils/auth";
    
    // create an axios instance
    const service = axios.create({
      baseURL: "http://192.xxx.x.xx:8700", 
      timeout: 10000, // request timeout
      // headers: {
      //   "Content-Type": "multipart/form-data",
      // },
    });
    
    let apiCallNo = 0;
    let loadingInstance;
    
    // request interceptor
    // TODO 待优化
    service.interceptors.request.use(
      (config) => {
        if (config.data) {
          const { hideLoading, ...rest } = config.data;
          if (!hideLoading) {
            apiCallNo += 1;
            if (apiCallNo === 1) {
              loadingInstance = Loading.service();
            }
          }
          if (Object.keys(rest).length !== 0) {
            config.data = rest;
          } else if (typeof hideLoading === "boolean") {
            config.data = null;
          }
        } else {
          apiCallNo += 1;
          if (apiCallNo === 1) {
            loadingInstance = Loading.service();
          }
        }
    
        if (store.getters.token) {
          // let each request carry token
          // ['X-Token'] is a custom headers key
          // please modify it according to the actual situation
          // config.headers["X-Token"] = getToken();
        }
        return config;
      },
      (error) => {
        // do something with request error
        return Promise.reject(error);
      }
    );
    
    // response interceptor
    service.interceptors.response.use(
      (response) => {
        apiCallNo -= 1;
        if (apiCallNo === 0) {
          loadingInstance.close();
        }
        const res = response.data;
    
        // 导出二进制流数据  
        if (res.type) {
          return res;
        }
       
        if (res.status !== 200) {
          Message({
            message: res.message || "Error",
            type: "error",
            duration: 5 * 1000,
          });
          return Promise.reject(new Error(res.message || "Error"));
        } else {
          return res.data;
        }
      },
      (error) => {
        console.log(error.response);
        apiCallNo -= 1;
        if (apiCallNo === 0) {
          loadingInstance.close();
        }
        Message({
          message: error.response?.data.message ?? "网络异常,请重试", // 统一的提示
          type: "error",
          duration: 5 * 1000,
        });
        return Promise.reject(error);
      }
    );
    
    export default service;

    二进制数据流返回的结果会有type属性,但是没有status这些属性,根据这个将普通数据和二进制分开。

    axios接口封装:

    export function exportList(data) {
      return request({
        url: "/api/demo/result/exportResult",
        method: "post",
        responseType: "blob",
        data,
      });
    }

    最重要的是 responseType: "blob", 这句代码会将后端传过来的数据流格式化成二进制如下:

    导出方法: exportData

    exportData() {
          if (this.multipleSelection.length === 0) {
            this.$message.error("请选择要导出的数据");
            return false;
          }
    
          this.exportList({
            id: this.multipleSelection.join(","),
          });
          // 清除
          this.multipleSelection.length = 0;
        },
    
    
    async exportList(reqData) {
          const res = await exportList(reqData);
          console.log("export:", res);
          const blob = new Blob([res], {
            type:
              "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8",
          });
          const aEle = document.createElement("a"); // 创建a标签
          const href = window.URL.createObjectURL(blob); // 创建下载的链接
          aEle.href = href;
          aEle.download = "信用评价模型数据.xlsx"; // 下载后文件名
          document.body.appendChild(aEle);
          aEle.click(); // 点击下载
          document.body.removeChild(aEle); // 下载完成移除元素
          window.URL.revokeObjectURL(href); // 释放掉blob对象
        },
    上面的写法就是用从服务器接收到的文件流(content-type:application/octet-stream)创建了一个blob对象,并使用该blob 创建一个指向类型数组的URL,将该url作为a标签的链接目标,然后去触发a标签的点击事件从而实现表格下载。
    注意上面在封装请求方法的时候已经将响应类型resposeType设置成了blob对象,所以在上面的请求函数中可以不加new Blob()这个步骤,加上就有点重复了
    async exportList(reqData) {
          const res = await exportList(reqData);
          console.log("export:", res);
          // const blob = new Blob([res], {
          //   type:
          //     "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8",
          // });
          const aEle = document.createElement("a"); // 创建a标签
          const href = window.URL.createObjectURL(res); // 创建下载的链接
          aEle.href = href;
          aEle.download = "信用报告模型.xlsx"; // 下载后文件名
          document.body.appendChild(aEle);
          aEle.click(); // 点击下载
          document.body.removeChild(aEle); // 下载完成移除元素
          window.URL.revokeObjectURL(href); // 释放掉blob对象
        },
     
    除了使用axios请求之外,还有a标签也可以下载二进制数据流的文件,通过a标签打开一个新的链接。下面是具体的实现:
    <a :href="hrefValue">导出数据</a>
    computed: {
        hrefValue() {
          return this.multipleSelection.length === 0
            ? ""
            : "/api/demo/result/exportExcel?ids=" +
                this.multipleSelection.join(",");
        },
      },
    multipleSelection是选择的数据的id集合,最后通过字符串的形式传递给后端。
    a标签这种方法比axios简单许多。推荐使用这种方法。
    这种写法需要设置代理服务。不然请求不到
     在vue.config.js中设置代理服务:
    devServer: {
        port: port,
        open: true,
        overlay: {
          warnings: false,
          errors: true,
        },
        proxy: {
          "/api": {
            target: "http://192.xxx.xx.xx:8000",
          },
          "/profile": {
            target: "http://192.xxx.xx.xx:8000
    ", }, }, },

    这样请求路径就变成了  http://192.xxx.xx.xx:8000/api/demo/result/exportExcel?ids=" +this.multipleSelection.join(",")

     
     
     
  • 相关阅读:
    视频学习网站
    保存文章
    maven常见命令总结
    Eclipse vs IDEA快捷键对比大全(win系统)
    JS调用android逻辑方法
    【原创】不用封装jar包 直接引入工程使用的方法(类似android的 is Library功能)
    windows下eclipse+hadoop2
    Solaris用户管理(一):用户与组管理
    jquery 操作 checkbox
    模拟用户登录的操作
  • 原文地址:https://www.cnblogs.com/lyt0207/p/13554884.html
Copyright © 2011-2022 走看看