由于公司业务的开发需要,需要实现在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 ,由于这种方法会导致新建窗口,故没有做实验