Vue實(shí)現(xiàn)點(diǎn)擊按鈕下載文件的操作代碼(后端Java)
上篇文章給大家介紹過vue實(shí)現(xiàn)點(diǎn)擊按鈕下載文件功能,今天繼續(xù)vue點(diǎn)擊按鈕下載文件的話題。
最近項(xiàng)目中需要實(shí)現(xiàn)點(diǎn)擊按鈕下載文件的需求,前端用的vue,因?yàn)槲募歉鞣N類型的,比如圖片、pdf、word之類的。這里后端是可以返回文件的地址給前端的,但我看了下網(wǎng)上各種五花八門的答案,感覺都不是我想要的。
因?yàn)椴淮_定文件是哪種類型的,所以我們?cè)诒4嫖募綌?shù)據(jù)庫的時(shí)候,應(yīng)該把文件的 Content-Type 一起存入,這樣從數(shù)據(jù)庫取出返回前端的時(shí)候,帶上 Content-Type 標(biāo)識(shí)是哪種類型的文件,前端解析即可。
1、后端代碼
這里我先寫后端的接口,考慮一下后端需要什么東西。因?yàn)槲募畔⒁呀?jīng)提前存入數(shù)據(jù)庫,所以我們只需要傳入主鍵id就可以拿到文件的信息。確定參數(shù)后,就需要確定一下返回值類型。這里可以使用 ResponseEntity 返回。 ResponseEntity 可以一次返回多個(gè)信息,包括狀態(tài)碼,響應(yīng)頭信息,響應(yīng)內(nèi)容等。
話不多說,看代碼。
/** * 下載附件 * @param attachmentId * @return */ public ResponseEntity<byte[]> download(Long attachmentId) { // 查詢附件是否存在 SysAttachment sysAttachment = sysAttachmentMapper.selectSysAttachmentById(attachmentId); if (StringUtils.isNull(sysAttachment)) { return null; } ByteArrayOutputStream bos = null; InputStream ins = null; try { String fileName = sysAttachment.getOrgFileName(); String ossFileName = sysAttachment.getUrl(); bos = new ByteArrayOutputStream(); ins = OssUtils.getInstance().getObject(ossFileName).getObjectContent(); // 取流中的數(shù)據(jù) int len = 0; byte[] buf = new byte[256]; while ((len = ins.read(buf, 0, 256)) > -1) { bos.write(buf, 0, len); } // 防止中文亂碼 fileName = URLEncoder.encode(fileName, "utf-8"); // 設(shè)置響應(yīng)頭 HttpHeaders headers = new HttpHeaders(); headers.add("Content-Disposition", "attachment;filename=" + fileName); headers.add("Content-Type", sysAttachment.getContentType()); // 設(shè)置響應(yīng)嗎 HttpStatus statusCode = HttpStatus.OK; ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(bos.toByteArray(), headers, statusCode); return response; } catch (Exception e) { throw new CustomException("下載失敗"); } finally { try { if (ins != null) { ins.close(); } if (bos != null) { bos.close(); } } catch (Exception e) { throw new CustomException("下載失敗"); } } }
這里我們從數(shù)據(jù)庫拿出文件的url后,再通過阿里云oss拿到文件的輸入流,接著把文件輸出為二進(jìn)制,封裝到 ResponseEntity 中,并把文件的類型設(shè)置到 Content-Type 中,同時(shí)為了防止文件名帶有中文名亂碼,設(shè)置 utf-8 編碼,至此后端接口完成。
通過上面的信息,我們?cè)跀?shù)據(jù)庫保存文件信息時(shí),至少應(yīng)該保存下面幾個(gè)字段:文件的url(一般在上傳到oss后會(huì)給你一個(gè))、文件的類型、原始文件名、文件大小等。
2、前端代碼
有了后端接口,接下來就是前端了。這里可以把文件下載的方法封裝成一個(gè)通用方法全局掛載,之后需要使用的地方直接使用即可。
我們需要標(biāo)識(shí)不同的文件,所以我們需要一個(gè)鍵值對(duì)表示不同的文件。
const mimeMap = { xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', xls: 'application/vnd.ms-excel', zip: 'application/zip', jpg: 'image/jpg', jpeg: 'image/jpeg', png: 'image/png', doc: 'application/msword', docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', ppt: 'application/vnd.ms-powerpoint', txt: 'text/plain', pdf: 'application/pdf' }
有需要的可以繼續(xù)補(bǔ)充。接下來自然就是發(fā)請(qǐng)求了,這里的返回類型可以設(shè)置為 blob ,使用axios直接發(fā)送。
/** * 下載附件 * @param path 接口地址 * @param param 請(qǐng)求參數(shù) */ export function downloadAttachment(path, param) { var url = baseUrl + path + param axios({ method: 'get', url: url, responseType: 'blob', headers: { 'Authorization': getToken() } }).then(res => { resolveBlob(res, res.data.type) }) }
接口地址和請(qǐng)求參數(shù)從外部傳入。同時(shí)需要攜帶token,不然會(huì)跨域訪問。拿到后端返回的數(shù)據(jù)后,需要解析二進(jìn)制文件,這里定義 resolveBlob 方法,該方法有兩個(gè)參數(shù),返回對(duì)象和文件的類型,文件的類型,我們?cè)诤蠖艘呀?jīng)放入 Content-Type 中了,這里直接取。
/** * 解析blob響應(yīng)內(nèi)容并下載 * @param {*} res blob響應(yīng)內(nèi)容 * @param {String} mimeType MIME類型 */ export function resolveBlob(res, mimeType) { const aLink = document.createElement('a') var blob = new Blob([res.data], { type: mimeType }) // 從response的headers中獲取filename, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 設(shè)置的文件名; var patt = new RegExp('filename=([^;]+\\.[^\\.;]+);*') var contentDisposition = decodeURI(res.headers['content-disposition']) var result = patt.exec(contentDisposition) var fileName = result[1] fileName = fileName.replace(/\"/g, '') aLink.href = URL.createObjectURL(blob) aLink.setAttribute('download', fileName) // 設(shè)置下載文件名稱 document.body.appendChild(aLink) aLink.click() document.body.removeChild(aLink); }
這代碼不用多解釋了吧,前端大佬們自然看得懂。OK了啊,到這里前后端代碼都完成了。
3、使用
使用那就更簡單啦。先掛載到全局
import { downloadAttachment } from "@/utils/download" Vue.prototype.downloadAttac = downloadAttachment
在使用的地方直接調(diào)用即可
<el-button type="text" icon="el-icon-download" size="mini" @click="downloadAttachRow(scope.row.attachmentId)" ></el-button> /** 下載附件 */ downloadAttachRow(attachId) { this.$confirm('是否確認(rèn)下載該文件?', "警告", { confirmButtonText: "確定", cancelButtonText: "取消", type: "warning" }).then(() => { this.downloadAttac('/system/attachment/download/', attachId) }).then(() => { this.msgSuccess("下載成功") }).catch(() => {}) }
到此結(jié)束。
到此這篇關(guān)于Vue實(shí)現(xiàn)點(diǎn)擊按鈕下載文件的操作代碼(后端Java)的文章就介紹到這了,更多相關(guān)Vue點(diǎn)擊按鈕下載文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue用復(fù)選框?qū)崿F(xiàn)組件且支持單選和多選操作方式
這篇文章主要介紹了vue用復(fù)選框?qū)崿F(xiàn)組件且支持單選和多選操作方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04vue3使用vue-cli引入windicss報(bào)錯(cuò)Can‘t resolve windi.css問題
這篇文章主要介紹了vue3使用vue-cli引入windicss報(bào)錯(cuò)Can‘t resolve windi.css問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03vue2使用element-ui,el-table不顯示,用npm安裝方式
這篇文章主要介紹了vue2使用element-ui,el-table不顯示,用npm安裝方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07Vuex unknown action type報(bào)錯(cuò)問題及解決
這篇文章主要介紹了Vuex unknown action type報(bào)錯(cuò)問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02moment轉(zhuǎn)化時(shí)間戳出現(xiàn)Invalid Date的問題及解決
這篇文章主要介紹了moment轉(zhuǎn)化時(shí)間戳出現(xiàn)Invalid Date的問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05Vue通過路由實(shí)現(xiàn)頁面間參數(shù)的傳遞
這篇文章主要介紹了Vue通過路由實(shí)現(xiàn)頁面間參數(shù)的傳遞,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04