Vue 前端導(dǎo)出后端返回的excel文件方式
前端導(dǎo)出后端返回的excel文件
在網(wǎng)上搜索了一番之后,決定采用Blob方式,這也是大家推薦的一種的方式,特此做下記錄。
頁(yè)面:
先篩選,向后端請(qǐng)求接口返回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', '外賣(mài)統(tǒng)計(jì)_' + num + '.xlsx') document.body.appendChild(link) link.click() document.body.removeChild(link) })
仔細(xì)看axios請(qǐng)求加了個(gè)responseType: 'blob'配置,這是很重要的
可以看到請(qǐng)求返回了一個(gè)Blob對(duì)象,你如果沒(méi)有正確的加上responseType: 'blob’這個(gè)參數(shù),返回的就不是個(gè)Blob對(duì)象,而是字符串了。
然后就自動(dòng)下載了!
處理文件的下載(后端Excel導(dǎo)出)
大概有兩種方法(通常對(duì)應(yīng)的是需要不需要攜帶 token),原理都是通過(guò) a 標(biāo)簽下載
- 通過(guò) Ajax 請(qǐng)求,拿到 response ,轉(zhuǎn)換為 blob 格式(主要是為了處理 type),為其生成下載鏈接,下載即可
- 直接拼接 URL,拼出來(lái)對(duì)應(yīng)請(qǐng)求鏈接,直接訪問(wèn)即可(不需要二次 token 認(rèn)證)
后端文件流
首先點(diǎn)擊導(dǎo)出 Excel ,這里調(diào)用接口成功
接下來(lái)看一下后臺(tái)返回的數(shù)據(jù)是什么樣,是文件流格式(OutputStream)
在處理之前,說(shuō)幾個(gè)要注意的點(diǎn)!?。?/strong>
1.注意:后端在這里一般會(huì)設(shè)置如下幾個(gè)請(qǐng)求頭
后端還可能開(kāi)啟 jwt token 驗(yàn)證,如果開(kāi)啟請(qǐng)移步第 2 點(diǎn)請(qǐng)求攔截設(shè)置 headers
注意: 由于跨域?yàn)g覽器處于安全考慮不讓自定義響應(yīng)頭通過(guò) JS 獲取 ,也就是說(shuō) Content-Disposition 前端在 Network 里是能看到的,但是無(wú)法通過(guò) JS 獲取到,這里后端需要將其暴露出去
跨域情況默認(rèn)只暴露:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma 六個(gè)屬性
// 設(shè)置返回類型為excel response.setContentType("application/vnd.ms-excel; charset=UTF-8"); // 設(shè)置返回文件名為filename.xls response.setHeader("Content-Disposition", "filename.xls"); // 請(qǐng)求或響應(yīng)消息不能走緩存 response.setHeader("Cache-Control", "no-cache"); // 將Content-Disposition暴露出去,這樣就可以用過(guò)JS獲取到了 response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
2.注意:前端在 Axios 請(qǐng)求和響應(yīng)攔截的時(shí)候,需要對(duì)其進(jìn)行處理
請(qǐng)求攔截一般我們都是會(huì)設(shè)置 headers,這里只是簡(jiǎn)單處理一下,實(shí)際會(huì)根據(jù)不同情況設(shè)置 headers
響應(yīng)攔截一般我們都是把 response.data 進(jìn)行返回,但是這里我們需要把整個(gè) response 返回(因?yàn)槲募?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 }) // 請(qǐng)求攔截器 service.interceptors.request.use( config => { config.headers[AUTHOR_KEY] = getToken() return config }, error => console.log(error) ) // 響應(yīng)攔截器 service.interceptors.response.use( response => { if (response.config.responseType === 'blob') { return response } return response.data }, error => console.log(error) ) export default service
接下來(lái)要處理這個(gè)文件流,大概有兩種方法(通常對(duì)應(yīng)的是需要不需要攜帶 token),原理都是通過(guò) a 標(biāo)簽下載
- 通過(guò) Ajax 請(qǐng)求,拿到 response ,轉(zhuǎn)換為 blob 格式(主要是為了處理 type),為其生成下載鏈接,下載即可
- 拼接 URL,拼出來(lái)對(duì)應(yīng)請(qǐng)求鏈接,直接訪問(wèn)即可
通過(guò) Blob 下載
Blob 通常用于存儲(chǔ)大文件,典型的 Blob 內(nèi)容是一張圖片或一個(gè)音頻
默認(rèn)情況下 axios 不會(huì)處理二進(jìn)制數(shù)據(jù),即請(qǐng)求可以正常被瀏覽器接收,但 axios 不會(huì)去處理。需要在請(qǐng)求的時(shí)候設(shè)置 responseType: 'blob' 才可以
- 拿到文件流之后,需要生成一個(gè) URL 才可以下載,可以通過(guò)URL.createObjectURL()方法生成一個(gè)鏈接
- a 標(biāo)簽添加文件名
- 正常情況下,通過(guò) window.location = url 就可以下載文件。瀏覽器判斷這個(gè)鏈接是一個(gè)資源而不是頁(yè)面的時(shí)候,就會(huì)下載文件。但是通過(guò)文件流生成的 url 對(duì)應(yīng)的資源是沒(méi)有文件名的,需要添加文件名。這時(shí)候可以用到 download 屬性指定下載的文件名
由于有瀏覽器問(wèn)題可能會(huì)出現(xiàn) content-disposition 匹配不到,最好做一下判斷看 content-disposition 和 Content-Disposition 哪個(gè)能取到
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標(biāo)簽,并處理二級(jí)制數(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) // 設(shè)置下載文件名稱 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對(duì)象 window.URL.revokeObjectURL(aLink.href) document.body.removeChild(aLink) }
注意:一般情況下文件名都是需要匹配的,后端傳過(guò)來(lái)的可能是這樣的,首選需要 decodeURI 解碼一下,再用正則把文件名匹配出來(lái)(替換設(shè)置下載文件名那里即可)
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沒(méi)有暴露,給文件一個(gè)默認(rèn)名字 if (fileName == null) fileName = '日?qǐng)?bào)表' aLink.setAttribute('download', fileName) document.body.appendChild(aLink) aLink.click() // 釋放URL對(duì)象 window.URL.revokeObjectURL(aLink.href) document.body.removeChild(aLink) }
拼接 URL 下載
如果可以直接通過(guò) URL 下載文件,則可以不需要發(fā)送 Ajax 請(qǐng)求(前提是沒(méi)有 token、headers 驗(yàn)證),直接下載
可以使用 a 標(biāo)簽進(jìn)行下載
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') }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Vue實(shí)現(xiàn)導(dǎo)出excel表格功能
- vue中導(dǎo)出Excel表格的實(shí)現(xiàn)代碼
- Vue結(jié)合后臺(tái)導(dǎo)入導(dǎo)出Excel問(wèn)題詳解
- 詳解如何在Vue項(xiàng)目中導(dǎo)出Excel
- Vue前端導(dǎo)出Excel文件的詳細(xì)實(shí)現(xiàn)方案
- 使用vue導(dǎo)出excel遇到的坑及解決
- vue導(dǎo)出excel表格的新手詳細(xì)教程
- vue實(shí)現(xiàn)導(dǎo)出excel的多種方式總結(jié)
- Vue純前端如何實(shí)現(xiàn)導(dǎo)出簡(jiǎn)單Excel表格的功能
相關(guān)文章
vue柱狀進(jìn)度條圖像的完美實(shí)現(xiàn)方案
本文是對(duì)bar進(jìn)度條實(shí)現(xiàn)的2種方案進(jìn)行分享,第一種是很簡(jiǎn)單,純css的實(shí)現(xiàn),第二種是echart的實(shí)現(xiàn)。對(duì)vue柱狀進(jìn)度條圖像的實(shí)現(xiàn)方案,感興趣的朋友跟隨小編一起看看吧2019-08-08vue3+vite加載本地js/json文件不能使用require淺析
這篇文章主要給大家介紹了關(guān)于vue3+vite加載本地js/json文件不能使用require的相關(guān)資料,require 是屬于 Webpack 的方法,在v3+vite的項(xiàng)目里面并不適用,需要的朋友可以參考下2023-07-07vue-cli 引入jQuery,Bootstrap,popper的方法
這篇文章主要介紹了vue-cli 引入jQuery,Bootstrap,popper的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-09-09uniapp和vue組件之間的傳值(父子傳值,兄弟傳值,跨級(jí)傳值,vuex)
這篇文章主要介紹了uniapp和vue組件之間的傳值(父子傳值,兄弟傳值,跨級(jí)傳值,vuex),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05使用vue-cli+webpack搭建vue開(kāi)發(fā)環(huán)境的方法
這篇文章主要介紹了使用vue-cli+webpack搭建vue開(kāi)發(fā)環(huán)境的方法,需要的朋友可以參考下2017-12-12vue3中使用vuex和vue-router的詳細(xì)步驟
這篇文章主要介紹了vue3中使用vuex和vue-router的步驟,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12vue監(jiān)視器@Watch創(chuàng)建執(zhí)行immediate方式
這篇文章主要介紹了vue監(jiān)視器@Watch創(chuàng)建執(zhí)行immediate方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08vue表格n-form中自定義增加必填星號(hào)的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue表格n-form中自定義增加必填星號(hào),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2024-12-12