由於公司業務的開發需要,需要實現在electron上實現PDF的線上預覽功能。electron 3.x版本後就不在支援PDF的預覽功能了,官方給的解釋是由於人手不夠將不再支援PDF預覽功能(也是醉了),在經過一番調研結合大佬們的經驗實現了PDF的在線上預覽功能
實現方式一、
-
將下好的檔案放入static檔案目錄下
-
在electron的主執行緒中通過渲染執行緒與主執行緒之間的通訊獲取viewer.html檔案位置
// 監聽獲取viewer.html檔案位置、 function getUrl(win) { const filePath = process.env.NODE_ENV === 'development' ? `${__static}\\pdfjs\\web\\viewer.html` : path.resolve(__dirname, '../../../static/pdfjs/web/viewer.html') win.webContents.send('recieve', filePath) } // pdf預覽獲取viewer.html檔案位置 ipcMain.on('getUrl', () => getUrl(win)) 複製程式碼
-
在pdf.vue中寫
<template> <iframe :src="base + '?file=' + url" :width="width" :height="height" class="iframe-placeholder"></iframe> </template> <script> import { ipcRenderer } from 'electron' // eslint-disable-line export default { props: { url: { type: String, default: '', }, width: { type: Number, default: 750 }, height: { type: Number, default: 600 }, }, data() { return { preview: false, base: '', } }, computed: { // 講義檔名 name() { const uri = decodeURI(this.url) const arr = uri.split('/') const len = arr.length return arr[len - 1] }, }, created() { // 獲取viewer.html的位置 ipcRenderer.send('getUrl') }, mounted() { ipcRenderer.on('recieve', (e, arg) => { console.log('檔案路徑', arg) this.base = arg }) } } </script> <style lang="scss" scoped> .wrapper { .info { width: 200px; } .iframe-placeholder { background: url('../../../assets/loading.svg') no-repeat 50% 50%; } } </style> 複製程式碼
-
在需要引入的地方引用即可
問題
樣式比較醜,但是可以實現PDF的分頁和列印的功能,且在打完包後檔案比較大
實現方式二、
-
下載npm pdfjs-dist 包
// npm的下載方式 npm i pdfjs-dist // yarn 的下載方式 yarn add pdfjs-dist 複製程式碼
-
在webpack的配置中寫入
entry: { renderer: path.join(__dirname, '../src/renderer/main.js'), 'pdf.worker': 'pdfjs-dist/build/pdf.worker.entry', }, 複製程式碼
-
在pdf.vue中寫入
<template> <el-dialog :visible.sync="pdfjsView" title="" width="55%" class="cpdf" append-to-body @close="pdfurl = null"> <div v-loading="loading" v-if="pdfurl" class="center" style="height:600px"> <canvas v-for="data in canvasData" :key="data" :id="'the-canvas-'+data" class="canvasstyle"></canvas> </div> <div v-else style="font-size:18px;text-align:center;font-weight:900"> 沒有PDF檔案可以預覽 </div> <span slot="footer"> <el-button @click="pdfjsView = false">取 消</el-button> <el-button type="primary" @click="pdfjsView = false">確 定</el-button> </span> </el-dialog> </template> <script type="text/ecmascript-6"> import PDFJS from 'pdfjs-dist' export default { name: 'CPdf', components: {}, data() { return { pdfDoc: null, // pdfjs 生成的物件 pageNum: 1, // pageRendering: false, pageNumPending: null, scale: 1.2, // 放大倍數 page_num: 0, // 當前頁數 page_count: 0, // 總頁數 maxscale: 2, // 最大放大倍數 minscale: 0.8, // 最小放大倍數 canvasData: [], pdfjsView: false, pdfurl: null, loading: false } }, methods: { renderPage(num) { // 渲染pdf const vm = this this.pageRendering = true const canvas = document.getElementById(`the-canvas-${num}`) // Using promise to fetch the page this.pdfDoc.getPage(num).then((page) => { const viewport = page.getViewport(vm.scale) // alert(vm.canvas.height) canvas.height = viewport.height canvas.width = viewport.width // Render PDF page into canvas context const renderContext = { // canvasContext: vm.ctx, canvasContext: canvas.getContext('2d'), viewport } const renderTask = page.render(renderContext) // Wait for rendering to finish renderTask.promise.then(() => { vm.pageRendering = false if (vm.pageNumPending !== null) { // New page rendering is pending vm.renderPage(vm.pageNumPending) vm.pageNumPending = null } }) }) vm.page_num = vm.pageNum }, getUrl(url) { this.pdfurl = url this.pdfjsView = true this.showPDf() }, showPDf() { const vm = this this.loading = true vm.canvasData = [] // PDFJS.workerSrc = '../../../static/PDF/pdf.worker.min.js' PDFJS.getDocument(vm.pdfurl) .then((pdfDoc_) => { // 初始化pdf vm.pdfDoc = pdfDoc_ vm.page_count = vm.pdfDoc.numPages for (let i = 0; i < vm.page_count; i += 1) { vm.canvasData.push(i + 1) } return pdfDoc_ }) .then((pdfDoc_) => { // 初始化pdf vm.pdfDoc = pdfDoc_ vm.page_count = vm.pdfDoc.numPages for (let i = 0; i < vm.page_count; i += 1) { vm.renderPage(i + 1) } vm.loading = false }) } }, computed: {}, mounted() {} } </script> <style lang="scss" scoped type="text/css"> .cpdf { top: 0; left: 0; width: 100%; height: 100%; z-index: 99999; display: flex; justify-content: center; align-items: center; .center { text-align: center; height: 100%; overflow: auto; padding-top: 20px; .contor { margin-bottom: 10px; } } .page-foot { position: fixed; left: 0px; bottom: 0px; width: 100%; height: 56px; line-height: 56px; background-color: #fff; text-align: center; z-index: 10; .foot-button { display: inline-block; height: 56px; position: relative; top: -22px; left: 20px; } } } </style> 複製程式碼
-
在需要引入的地方引入即可
問題
實現方式三、
載入 npm i electron-pdf ,由於這種方法會導致新建視窗,故沒有做實驗