以前在工做中,有遇到過須要導出Excel的需求, 這裏整理了一下,通常前端在導出excel時, 多分爲兩種, 一種是後端返回二進制數據流, 另外一種是直接純前端生成(如導出一個模板). 而導出的方式可使用form表單提交, a標籤下載, window.open打開新窗口. 最經常使用的應該就是a標籤了.前端
這裏主要講兩種方式的文件下載方法, 和後端返回二進制數據流時,產生亂碼,及數據量過大致使網絡失敗的解決方法.ios
這種方法用的很少,通常文件下載仍是主要依賴於後端返回二進制數據流的形式實現. 這種方法通常用於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)
```
複製代碼
第一步: 安裝 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
},
複製代碼
對於導出數據而言,返回二進制流文件是最多見的, 而前端打開連接下載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標籤地址太長致使網絡失敗的問題就行.後端