vue項(xiàng)目用后端返回的文件流實(shí)現(xiàn)docx和pdf文件預(yù)覽
寫這篇文章的目的,是因?yàn)槲冶容^懶,想把代碼記錄一下,方便日后使用;哈哈,如果你也需要,也可以復(fù)制粘貼啊,為了方便自己和需要的人知道怎么使用,我盡量寫的詳細(xì)一點(diǎn),沒(méi)有什么技術(shù)難點(diǎn),就是簡(jiǎn)單的記錄,萬(wàn)一能幫到需要的人呢,也是一件美事;
其實(shí)也就是使用了兩個(gè)插件而已,docx-preview和vue-pdf,下面我們就寫一下使用方法和詳細(xì)的代碼;
實(shí)現(xiàn)效果圖
大家先看一下實(shí)現(xiàn)的效果,分別是docx文件預(yù)覽和pdf文件預(yù)覽;
原型是從一個(gè)table列表的操作中點(diǎn)擊查看源文件,跳轉(zhuǎn)到預(yù)覽頁(yè)面:
docx文件預(yù)覽
pdf文件預(yù)覽(可實(shí)現(xiàn)翻頁(yè)功能)
docx-preview文件預(yù)覽
首先安裝docx-preview
npm install docx-preview
點(diǎn)擊【查看源文件】
... <el-button type="text" @click="clickView(scope.row)">查看源文件</el-button> ...
在點(diǎn)擊事件方法中,首先進(jìn)行if判斷文件類型,不同的文件類型走不同的邏輯,這里判斷是否為.docx文件,然后進(jìn)行路由跳轉(zhuǎn)到文件預(yù)覽頁(yè)面,把id帶過(guò)去;
... //查看源文件 clickView(row){ if((row.fileName).indexOf('.docx') !== -1){ this.$router.push({ path: "/dataStandar/knowledgeBase/createBase/vuedocx", query: { //要傳的參數(shù) id: row.id, }, }); }else{ //這里代碼是pdf文件預(yù)覽,此處先省略 ... } }, ...
vueDocx.vue組件
<template> <div ref="file" class="files" style="width: 100%;"></div> </template> <script> import { getSourceFileById, //接口函數(shù)返回的文件流 } from '@/api/dataStandar/knowledgeBase/createBase' import {renderAsync } from "docx-preview"; //引入renderAsync 方法 export default { data(){ return { docxOptions: { className: "kaimo-docx-666", // string:默認(rèn)和文檔樣式類的類名/前綴 inWrapper: true, // boolean:?jiǎn)⒂脟@文檔內(nèi)容的包裝器渲染 ignoreWidth: false, // boolean:禁用頁(yè)面的渲染寬度 ignoreHeight: false, // boolean:禁止渲染頁(yè)面高度 ignoreFonts: false, // boolean:禁用字體渲染 breakPages: true, // boolean:在分頁(yè)符上啟用分頁(yè) ignoreLastRenderedPageBreak: true, // boolean:在 lastRenderedPageBreak 元素上禁用分頁(yè) experimental: false, // boolean:?jiǎn)⒂脤?shí)驗(yàn)功能(制表符停止計(jì)算) trimXmlDeclaration: true, // boolean:如果為true,解析前會(huì)從?? xmlTemplate 文檔中移除 xmlTemplate 聲明 useBase64URL: false, // boolean:如果為true,圖片、字體等會(huì)轉(zhuǎn)為base 64 URL,否則使用URL.createObjectURL useMathMLPolyfill: false, // boolean:包括用于 chrome、edge 等的 MathML polyfill。 showChanges: false, // boolean:?jiǎn)⒂梦臋n更改的實(shí)驗(yàn)性渲染(插入/刪除) debug: false, // boolean:?jiǎn)⒂妙~外的日志記錄 }, } }, mounted(){ this.initView() }, methods:{ initView(){ var id = this.$route.query.id this.loading = this.$loading({ lock: true, text: "正在加載...", spinner: 'el-icon-loading', background: 'rgba(0, 0, 0, 0.6)' }); getSourceFileById({},id).then(res => { let bodyContainer = this.$refs.file var data = res.data if(res.status == 200){ renderAsync( data, // Blob | ArrayBuffer | Uint8Array, 可以是 JSZip.loadAsync 支持的任何類型 bodyContainer, // HTMLElement 渲染文檔內(nèi)容的元素, null, // HTMLElement, 用于呈現(xiàn)文檔樣式、數(shù)字、字體的元素。如果為 null,則將使用 bodyContainer。 this.docxOptions // 配置 ) setTimeout(() => { this.loading.close() },1000) } }) }, } } </script> <style> .files{ padding: 0 20px; } </style>
以上就是docx文件預(yù)覽邏輯和代碼,使用比較簡(jiǎn)單;
pdf文件預(yù)覽
首先安裝vue-pdf
npm install vue-pdf
然后新建一個(gè)vuePdf.vue組件,直接復(fù)制粘貼使用即可,樣式可以根據(jù)自己需求修改,其他不用修改;
<template> <div id="container"> <!-- 上一頁(yè)、下一頁(yè) --> <div class="right-btn"> <!-- 輸入頁(yè)碼 --> <div class="pageNum"> <input v-model.number="currentPage" type="number" class="inputNumber" @input="inputEvent()" /> / {{ pageCount }} </div> <div @click="changePdfPage('first')" class="turn">首頁(yè)</div> <!-- 在按鈕不符合條件時(shí)禁用 --> <div @click="changePdfPage('pre')" class="turn-btn" :style="currentPage === 1 ? 'cursor: not-allowed;' : ''" > 上一頁(yè) </div> <div @click="changePdfPage('next')" class="turn-btn" :style="currentPage === pageCount ? 'cursor: not-allowed;' : ''" > 下一頁(yè) </div> <div @click="changePdfPage('last')" class="turn">尾頁(yè)</div> </div> <div class="pdfArea"> <!-- // 不要改動(dòng)這里的方法和屬性,下次用到復(fù)制就直接可以用 --> <pdf :src="src" ref="pdf" v-show="loadedRatio === 1" :page="currentPage" @num-pages="pageCount = $event" @progress="loadedRatio = $event" @page-loaded="currentPage = $event" @loaded="loadPdfHandler" @link-clicked="currentPage = $event" style="display: inline-block; width: 100%" id="pdfID" ></pdf> </div> <!-- 加載未完成時(shí),展示進(jìn)度條組件并計(jì)算進(jìn)度 --> <div class="progress" v-if="loadedRatio != 1"> <el-progress type="circle" :width="70" color="#53a7ff" :percentage=" Math.floor(loadedRatio * 100) ? Math.floor(loadedRatio * 100) : 0 " ></el-progress> <br /> <!-- 加載提示語(yǔ) --> <span>{{ remindShow }}</span> </div> </div> </template> <script> import pdf from "vue-pdf"; export default { components: { pdf, }, data() { return { // ----- loading ----- remindText: { loading: "加載文件中,文件較大請(qǐng)耐心等待...", refresh: "若卡住不動(dòng),可刷新頁(yè)面重新加載...", }, remindShow: "加載文件中,文件較大請(qǐng)耐心等待...", intervalID: "", src: "", // 當(dāng)前頁(yè)數(shù) currentPage: 0, // 總頁(yè)數(shù) pageCount: 0, // 加載進(jìn)度 loadedRatio: 0, }; }, created() { // 頁(yè)面加載,拿到路由中的url復(fù)制給data中的src this.src = this.$route.query.url; console.log(this.src); }, mounted() { // // 更改 loading 文字 this.intervalID = setInterval(() => { this.remindShow === this.remindText.refresh ? (this.remindShow = this.remindText.loading) : (this.remindShow = this.remindText.refresh); }, 4000); }, methods: { // 頁(yè)面回到頂部 toTop() { document.getElementById("container").scrollTop = 0; }, // 輸入頁(yè)碼時(shí)校驗(yàn) inputEvent() { if (this.currentPage > this.pageCount) { // 1. 大于max this.currentPage = this.pageCount; } else if (this.currentPage < 1) { // 2. 小于min this.currentPage = 1; } }, // 切換頁(yè)數(shù) changePdfPage(val) { if (val === "pre" && this.currentPage > 1) { // 切換后頁(yè)面回到頂部 this.currentPage--; this.toTop(); } else if (val === "next" && this.currentPage < this.pageCount) { this.currentPage++; this.toTop(); } else if (val === "first") { this.currentPage = 1; this.toTop(); } else if (val === "last" && this.currentPage < this.pageCount) { this.currentPage = this.pageCount; this.toTop(); } }, // pdf加載時(shí) loadPdfHandler(e) { // 加載的時(shí)候先加載第一頁(yè) this.currentPage = 1; }, }, destroyed() { // 在頁(yè)面銷毀時(shí)記得清空 setInterval clearInterval(this.intervalID); }, }; </script> <style scoped> #container { position: absolute !important; left: 0; right: 0; bottom: 0; top: 50px; background: #f4f7fd; overflow: auto; font-family: PingFang SC; width: 100%; display: flex; /* justify-content: center; */ position: relative; } /* 右側(cè)功能按鈕區(qū) */ .right-btn { position: fixed; right: 5%; bottom: 15%; width: 120px; display: flex; flex-wrap: wrap; justify-content: center; z-index: 99; } .pdfArea { width: 900px; margin: 0 auto; } /* ------------------- 輸入頁(yè)碼 ------------------- */ .pageNum { margin: 10px 0; font-size: 18px; } /*在谷歌下移除input[number]的上下箭頭*/ input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { -webkit-appearance: none !important; margin: 0; } /*在firefox下移除input[number]的上下箭頭*/ input[type="number"] { -moz-appearance: textfield; } .inputNumber { border-radius: 8px; border: 1px solid #999999; height: 35px; font-size: 18px; width: 60px; text-align: center; } .inputNumber:focus { border: 1px solid #00aeff; background-color: rgba(18, 163, 230, 0.096); outline: none; transition: 0.2s; } /* ------------------- 切換頁(yè)碼 ------------------- */ .turn { background-color: #164fcc; opacity: 0.9; color: #ffffff; height: 70px; width: 70px; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 5px 0; } .turn-btn { background-color: #164fcc; opacity: 0.9; color: #ffffff; height: 70px; width: 70px; border-radius: 50%; margin: 5px 0; display: flex; align-items: center; justify-content: center; } .turn-btn:hover, .turn:hover { transition: 0.3s; opacity: 0.5; cursor: pointer; } /* ------------------- 進(jìn)度條 ------------------- */ .progress { position: absolute; right: 50%; top: 50%; text-align: center; } .progress > span { color: #199edb; font-size: 14px; } </style>
點(diǎn)擊【查看源文件】
... <el-button type="text" @click="clickView(scope.row)">查看源文件</el-button> ...
查看源文件方法
... //查看源文件 clickView(row){ if((row.fileName).indexOf('.docx') !== -1){ //這里代碼是docx文件預(yù)覽,此處省略 ... }else{ this.loading = this.$loading({ lock: true, text: "正在加載...", spinner: 'el-icon-loading', background: 'rgba(0, 0, 0, 0.6)' }); //接口函數(shù)傳入id,返回的文件流 getSourceFileById({},row.id).then(res => { var data = res.data var binaryData = []; binaryData.push(data); let url = window.URL.createObjectURL( new Blob(binaryData, { type: "application/pdf;charset=utf-8", }) ); if (url != null && url != undefined && url) { // vue路由跳轉(zhuǎn)并以問(wèn)號(hào)形式攜帶vue-pdf預(yù)覽時(shí)所需要的pdf地址 this.$router.push({ path: "/dataStandar/knowledgeBase/createBase/vuepdf", query: { //要傳的參數(shù) url: url, }, }); this.loading.close() } }) } }, ...
到此這篇關(guān)于vue項(xiàng)目用后端返回的文件流實(shí)現(xiàn)docx和pdf文件預(yù)覽的文章就介紹到這了,更多相關(guān)vue docx和pdf文件預(yù)覽內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用element-ui設(shè)置table組件寬度(width)為百分比
這篇文章主要介紹了使用element-ui設(shè)置table組件寬度(width)為百分比方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04Vue實(shí)現(xiàn)選項(xiàng)卡tab切換制作
這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)選項(xiàng)卡tab切換制作,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03vue 使用lodash實(shí)現(xiàn)對(duì)象數(shù)組深拷貝操作
這篇文章主要介紹了vue 使用lodash實(shí)現(xiàn)對(duì)象數(shù)組深拷貝操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-09-09Vue.js實(shí)現(xiàn)多條件篩選、搜索、排序及分頁(yè)的表格功能
這篇文章主要為大家詳細(xì)介紹了Vue.js實(shí)現(xiàn)多條件篩選、搜索、排序及分頁(yè)的表格功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03Vue2學(xué)習(xí)筆記之請(qǐng)求數(shù)據(jù)交互vue-resource
本篇文章主要介紹了Vue2學(xué)習(xí)筆記之?dāng)?shù)據(jù)交互vue-resource ,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02