前端文件下載導出Excel

前言

以前在工做中,有遇到過須要導出Excel的需求, 這裏整理了一下,通常前端在導出excel時, 多分爲兩種, 一種是後端返回二進制數據流, 另外一種是直接純前端生成(如導出一個模板). 而導出的方式可使用form表單提交, a標籤下載, window.open打開新窗口. 最經常使用的應該就是a標籤了.前端

正文

這裏主要講兩種方式的文件下載方法, 和後端返回二進制數據流時,產生亂碼,及數據量過大致使網絡失敗的解決方法.ios

1.純前端生成EXcel, 這裏更新一下, 增長導出xlsx格式的方法

這種方法用的很少,通常文件下載仍是主要依賴於後端返回二進制數據流的形式實現. 這種方法通常用於json格式數據導出模板 話很少說,先上代碼npm

```
 let str = ''
  const jsonData = [{ '倉庫代碼': '', '貨號': '', '尺碼': '', '條碼': '', '切貨數量': '', '折扣': '' }]
  console.log(jsonData)
  for (var k in jsonData[0]) {
    str += k + ','
  }
  str = str.slice(0, str.length - 1) + '\n'
  console.log(str)
  // 增長\t爲了避免讓表格顯示科學計數法或者其餘格式
  for (let i = 0; i < jsonData.length; i++) {
    for (const item in jsonData[i]) {
      str += `${jsonData[i][item] + '\t'},`
    }
    str += '\n'
  }
  // encodeURIComponent解決中文亂碼
  const uri = 'data:application/vnd.ms-excel;charset=utf-8,\ufeff' + encodeURIComponent(str)
  // 經過建立a標籤實現
  const link = document.createElement('a')
  link.href = uri
  // 對下載的文件命名
  link.download = '訂單模板.xls'
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
```
複製代碼

導出xlsx格式

第一步: 安裝 file-saver 和 xlsxjson

npm i file-saver xlsx -s
複製代碼
第二步: 在要用的組件用中引入
複製代碼
import FileSaver from 'file-saver'
 import XLSX from 'xlsx'
複製代碼
// 爲表格綁定一個id, 特別注意
<el-table
   id="table"
   :data="tableData"
   style="width: 100%">
   <el-table-column
     prop="date"
     label="日期"
     width="180">
   </el-table-column>
   <el-table-column
     prop="name"
     label="姓名"
     width="180">
   </el-table-column>
   <el-table-column
     prop="address"
     label="地址">
   </el-table-column>
 </el-table>
複製代碼

第三步:綁定導出按鈕的調用方法axios

getXlsx() {
             let wb = XLSX.utils.table_to_book(document.querySelector('#table'));
             /* #table 就是表格的id */
             let wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: true, type: 'array'});
             try {
                 FileSaver.saveAs(new Blob([wbout], {type: 'application/octet-stream'}), '導出數據.xlsx');
             } catch (e) {
                 if (typeof console !== 'undefined')
                     console.log(e, wbout)
             }
             return wbout


         },

複製代碼

2.後端返回二進制數據流,生成Excel

對於導出數據而言,返回二進制流文件是最多見的, 而前端打開連接下載excel文件通常有三種方式, 
第一種是form表單方式 , 也是同步下載方式,直接下載. 這種方式的優勢在於不須要對返回數據進行轉換操做, 瀏覽器會自動同步解析. 但缺點是沒法對返回結果進行操做, 如:通常工做中須要對請求進行鑑權, 這個時候,form表單方式下載是沒法在請求頭中帶上token的, 後端只能經過從cookie中獲取.

第二種是a標籤下載方式, 將返回結果處理成一個新連接, 經過建立a標籤打開, 這種方式的優勢在於內部請求不須要對鑑權作多餘處理, 也能夠拿到返回結果進行操做,
缺點在於不注意之間會產生亂碼,及數據量太大致使網絡失敗. 
使用blob容器能夠解決數據量大致使網絡失敗的問題, 
而亂碼問題在二進制流前拼接字符串'\ufeff'便可
```
 this.$axios({
      method: params.method,
      url: params.url,
      data: params.data,
      responseType: 'blob'  // 指明返回格式, 這裏註明一下, 若是導出EXCEL爲[object blob]的話, 能夠把這段responseType:'blob' 註釋掉試一下.  
    }).then(res => {
      console.log(res) // 返回結果
      // 這裏尤爲須要注意, '\ufeff' 用於解決亂碼問題, blob能夠解決數據量大致使網絡失敗.
      const blob = new Blob(['\ufeff' + res.data], { type: 'text/csv;charset=utf-8' })
      const url = window.URL.createObjectURL(blob)
      // 經過建立a標籤實現
      const link = document.createElement('a')
      link.href = url
      // 對下載的文件命名, 若是後端返回名稱出現亂碼, 須要後端編碼一下.
      link.download = decodeURI(res.headers['content-disposition'].split('=')[1]) || '發貨單導出數據表.csv'
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
    })
```
複製代碼

結語

功能不難,須要注意的是二進制流的轉換, 和a標籤地址太長致使網絡失敗的問題就行.後端

相關文章
相關標籤/搜索