Vue 前端導出后端返回的excel文件方式
前端導出后端返回的excel文件
在網(wǎng)上搜索了一番之后,決定采用Blob方式,這也是大家推薦的一種的方式,特此做下記錄。
頁面:

先篩選,向后端請求接口返回excel文件,代碼如下:
const apiUrl = this.Global.httpUrl + '/laima/export/new/exportTackOutOrder'
console.log(this.form)
let param = new URLSearchParams();
param.append("startDate", "2019-01-01");
param.append("endDate", "2019-02-01");
this.$axios.post(apiUrl, param,{responseType: 'blob'}).then((res) => {
console.log( res.data)
const link = document.createElement('a')
let blob = new Blob([res.data],{type: 'application/vnd.ms-excel'});
link.style.display = 'none'
link.href = URL.createObjectURL(blob);
let num = ''
for(let i=0;i < 10;i++){
num += Math.ceil(Math.random() * 10)
}
link.setAttribute('download', '外賣統(tǒng)計_' + num + '.xlsx')
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
})仔細看axios請求加了個responseType: 'blob'配置,這是很重要的

可以看到請求返回了一個Blob對象,你如果沒有正確的加上responseType: 'blob’這個參數(shù),返回的就不是個Blob對象,而是字符串了。
然后就自動下載了!
處理文件的下載(后端Excel導出)
大概有兩種方法(通常對應的是需要不需要攜帶 token),原理都是通過 a 標簽下載
- 通過 Ajax 請求,拿到 response ,轉換為 blob 格式(主要是為了處理 type),為其生成下載鏈接,下載即可
- 直接拼接 URL,拼出來對應請求鏈接,直接訪問即可(不需要二次 token 認證)
后端文件流
首先點擊導出 Excel ,這里調用接口成功

接下來看一下后臺返回的數(shù)據(jù)是什么樣,是文件流格式(OutputStream)

在處理之前,說幾個要注意的點?。?!
1.注意:后端在這里一般會設置如下幾個請求頭
后端還可能開啟 jwt token 驗證,如果開啟請移步第 2 點請求攔截設置 headers
注意: 由于跨域瀏覽器處于安全考慮不讓自定義響應頭通過 JS 獲取 ,也就是說 Content-Disposition 前端在 Network 里是能看到的,但是無法通過 JS 獲取到,這里后端需要將其暴露出去
跨域情況默認只暴露:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma 六個屬性
// 設置返回類型為excel
response.setContentType("application/vnd.ms-excel; charset=UTF-8");
// 設置返回文件名為filename.xls
response.setHeader("Content-Disposition", "filename.xls");
// 請求或響應消息不能走緩存
response.setHeader("Cache-Control", "no-cache");
// 將Content-Disposition暴露出去,這樣就可以用過JS獲取到了
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
2.注意:前端在 Axios 請求和響應攔截的時候,需要對其進行處理
請求攔截一般我們都是會設置 headers,這里只是簡單處理一下,實際會根據(jù)不同情況設置 headers
響應攔截一般我們都是把 response.data 進行返回,但是這里我們需要把整個 response 返回(因為文件名在 headers 里面)
import axios from 'axios'
import { getToken } from '@/utils/auth'
import { AUTHOR_KEY } from '@/global'
const service = axios.create({
baseURL: process.env.NODE_ENV === 'development' ? '' : 'http://127.0.0.1:9999'
withCredentials: true,
timeout: 5000
})
// 請求攔截器
service.interceptors.request.use(
config => {
config.headers[AUTHOR_KEY] = getToken()
return config
},
error => console.log(error)
)
// 響應攔截器
service.interceptors.response.use(
response => {
if (response.config.responseType === 'blob') {
return response
}
return response.data
},
error => console.log(error)
)
export default service
接下來要處理這個文件流,大概有兩種方法(通常對應的是需要不需要攜帶 token),原理都是通過 a 標簽下載
- 通過 Ajax 請求,拿到 response ,轉換為 blob 格式(主要是為了處理 type),為其生成下載鏈接,下載即可
- 拼接 URL,拼出來對應請求鏈接,直接訪問即可
通過 Blob 下載
Blob 通常用于存儲大文件,典型的 Blob 內容是一張圖片或一個音頻
默認情況下 axios 不會處理二進制數(shù)據(jù),即請求可以正常被瀏覽器接收,但 axios 不會去處理。需要在請求的時候設置 responseType: 'blob' 才可以
- 拿到文件流之后,需要生成一個 URL 才可以下載,可以通過URL.createObjectURL()方法生成一個鏈接
- a 標簽添加文件名
- 正常情況下,通過 window.location = url 就可以下載文件。瀏覽器判斷這個鏈接是一個資源而不是頁面的時候,就會下載文件。但是通過文件流生成的 url 對應的資源是沒有文件名的,需要添加文件名。這時候可以用到 download 屬性指定下載的文件名
由于有瀏覽器問題可能會出現(xiàn) content-disposition 匹配不到,最好做一下判斷看 content-disposition 和 Content-Disposition 哪個能取到
const mimeMap = {
xlsx: 'application/vnd.ms-excel',
zip: 'application/zip',
}
export const toExcel = params => {
return request({
method: 'get',
url: '/dayReportToExcel/toExcel',
responseType: 'blob',
params
}).then(res => resolveBlob(res, mimeMap.xlsx))
export function resolveBlob(res, mimeType) {
// 創(chuàng)建a標簽,并處理二級制數(shù)據(jù)
const aLink = document.createElement('a')
const blob = new Blob([res.data], { type: mimeType })
// 生成下載鏈接
const URL = window.URL || window.webkitURL
aLink.href = URL.createObjectURL(blob)
// 設置下載文件名稱
let fileName = ''
if (res.headers['content-disposition']) fileName = res.headers['content-disposition']
if (res.headers['Content-Disposition']) fileName = res.headers['Content-Disposition']
aLink.setAttribute('download', fileName)
// 下載
document.body.appendChild(aLink)
aLink.click()
// 釋放URL對象
window.URL.revokeObjectURL(aLink.href)
document.body.removeChild(aLink)
}
注意:一般情況下文件名都是需要匹配的,后端傳過來的可能是這樣的,首選需要 decodeURI 解碼一下,再用正則把文件名匹配出來(替換設置下載文件名那里即可)

export function resolveBlob(res, mimeType) {
const aLink = document.createElement('a')
const blob = new Blob([res.data], { type: mimeType })
const pat = new RegExp('filename=([^;]+\\.[^\\.;]+)')
let contentDisposition
if (res.headers['content-disposition']) contentDisposition = res.headers['content-disposition']
if (res.headers['Content-Disposition']) contentDisposition = res.headers['Content-Disposition']
const result = pat.exec(decodeURI(contentDisposition))
let fileName = result && result[1]
const URL = window.URL || window.webkitURL
aLink.href = URL.createObjectURL(blob)
// 如果Content-Disposition沒有暴露,給文件一個默認名字
if (fileName == null) fileName = '日報表'
aLink.setAttribute('download', fileName)
document.body.appendChild(aLink)
aLink.click()
// 釋放URL對象
window.URL.revokeObjectURL(aLink.href)
document.body.removeChild(aLink)
}
拼接 URL 下載
如果可以直接通過 URL 下載文件,則可以不需要發(fā)送 Ajax 請求(前提是沒有 token、headers 驗證),直接下載
可以使用 a 標簽進行下載
import qs from 'qs'
export function downloadExcel(params) {
const url = window.location.origin + '/dayReportToExcel/toExcel?' + qs.stringify(params)
const aLink = document.createElement('a')
aLink.setAttribute('download', '')
aLink.setAttribute('target', '_blank')
aLink.href = url
aLink.click()
}
可以使用 window.open(url, '_blank')
import qs from 'qs'
export function downloadExcel(params) {
const url = window.location.origin + '/dayReportToExcel/toExcel?' + qs.stringify(params)
window.open(url, '_blank')
}
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
element el-table 表格限制多選個數(shù)功能
這篇文章主要介紹了element el-table 表格限制多選個數(shù)功能,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-03-03
Vue循環(huán)組件加validate多表單驗證的實例
今天小編就為大家分享一篇Vue循環(huán)組件加validate多表單驗證的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09
Vue+Jwt+SpringBoot+Ldap完成登錄認證的示例代碼
本篇文章主要介紹了Vue+Jwt+SpringBoot+Ldap完成登錄認證的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05

