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(",")

 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM