pdf.js实战,含水印、电子签章解决方案
2020/5/20 11:26:35
本文主要是介绍pdf.js实战,含水印、电子签章解决方案,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
项目涉及到移动端查看电子合同的问题,前前后后试了三种方案,真是一步一个坑,三种方案各有各的优点,不水,直接上代码,按照自己的需求选择。
一、pdf-vue
直接使用vue-pdf插件,核心的代码是pdf.js,只不过就是自己封装了一下,优点是方便快捷,缺点是无法加载电子签章。
github地址: github.com/FranckFreib…
1、npm install pdf-vue --save
2、template代码
<template> <div class="pdf" v-show="fileType === 'pdf'"> <p class="arrow"> // 上一页 <span @click="changePdfPage(0)" class="turn" :class="{grey: currentPage==1}">Preview</span> {{currentPage}} / {{pageCount}} // 下一页 <span @click="changePdfPage(1)" class="turn" :class="{grey: currentPage==pageCount}">Next</span> </p> // 自己引入就可以使用,这里我的需求是做了分页功能,如果不需要分页功能,只要src就可以了 <pdf :src="src" // src需要展示的PDF地址 :page="currentPage" // 当前展示的PDF页码 @num-pages="pageCount=$event" // PDF文件总页码 @page-loaded="currentPage=$event" // 一开始加载的页面 @loaded="loadPdfHandler"> // 加载事件 </pdf> </div> </template> 复制代码
3、js代码
import pdf from 'vue-pdf' export default { components: {pdf}, data () { return { currentPage: 0, // pdf文件页码 pageCount: 0, // pdf文件总页数 fileType: 'pdf', // 文件类型     src: '', // pdf文件地址 } },   created: {     // 有时PDF文件地址会出现跨域的情况,这里最好处理一下     this.src = pdf.createLoadingTask(this.src)   } method: { // 改变PDF页码,val传过来区分上一页下一页的值,0上一页,1下一页 changePdfPage (val) { // console.log(val) if (val === 0 && this.currentPage > 1) { this.currentPage-- // console.log(this.currentPage) } if (val === 1 && this.currentPage < this.pageCount) { this.currentPage++ // console.log(this.currentPage) } }, // pdf加载时 loadPdfHandler (e) { this.currentPage = 1 // 加载的时候先加载第一页 } } } 复制代码
使用非常方便,尤其是只需要翻页,或者不需要翻页的,强烈推荐。
二、pdf-dist
pdf-dist也是基于pdf.js的一个组件,只不过没有封装,需要自己配置,优点是可配置,可实现特殊的需求,缺点是需要自己封装,水印可加载,网上说可以加载电子签章,我的加载不出来,所以还是没采用。
1、npm install pdf-dist --save
2、封装一个pdf.vue
<template> <div class="cpdf" id="cpdf"> <div class="center"> <canvas class="canvasstyle" id="the-canvas"></canvas> <div class="contor"> <button @click="prev" style="margin-right: 10px">上一页</button> <span>Page: <span v-text="page_num"></span> / <span v-text="page_count"></span></span> <button @click="next" style="margin-left: 10px">下一页</button> </div> </div> </div> </template> <script> import PDFJS from 'pdfjs-dist' export default { name: 'c-pdf', // 接收父组件传来的参数 props: ['pdfurl'], components: { }, data () { return { pdfDoc: null, // pdfjs 生成的对象 pageNum: 1, // pageRendering: false, pageNumPending: null, scale: 1, // 放大倍数 page_num: 0, // 当前页数 page_count: 0, // 总页数 maxscale: 2, // 最大放大倍数 minscale: 0.8// 最小放大倍数 } }, methods: { renderPage (num) { // 渲染pdf let vm = this this.pageRendering = true let canvas = document.getElementById('the-canvas') let ctx = canvas.getContext('2d') let bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1 let dpr = window.devicePixelRatio || 1 let ratio = dpr / bsr // Using promise to fetch the page this.pdfDoc.getPage(num).then(function (page) { var viewport = page.getViewport(screen.availWidth / page.getViewport(1).width) // alert(vm.canvas.height) canvas.height = ratio * viewport.width canvas.width = ratio * viewport.height canvas.style.width = 1.5 * viewport.width + 'px' canvas.style.height = 1 * viewport.height + 'px' ctx.setTransform(ratio, 0, 0, ratio, 0, 0) // Render PDF page into canvas context var renderContext = { canvasContext: ctx, viewport: viewport } var renderTask = page.render(renderContext) // Wait for rendering to finish renderTask.promise.then(function () { vm.pageRendering = false if (vm.pageNumPending !== null) { // New page rendering is pending vm.renderPage(vm.pageNumPending) vm.pageNumPending = null } }) }) vm.page_num = vm.pageNum }, addscale () { // 放大 if (this.scale >= this.maxscale) { return } this.scale += 0.1 this.queueRenderPage(this.pageNum) }, minus () { // 缩小 if (this.scale <= this.minscale) { return } this.scale -= 0.1 this.queueRenderPage(this.pageNum) }, prev () { // 上一页 let vm = this if (vm.pageNum <= 1) { return } vm.pageNum-- vm.queueRenderPage(vm.pageNum) }, next () { // 下一页 let vm = this if (vm.pageNum >= vm.page_count) { return } vm.pageNum++ vm.queueRenderPage(vm.pageNum) }, closepdf () { // 关闭PDF this.$emit('closepdf') }, queueRenderPage (num) { if (this.pageRendering) { this.pageNumPending = num } else { this.renderPage(num) } } }, computed: { ctx () { let id = document.getElementById('the-canvas') return id.getContext('2d') } }, mounted () { let vm = this PDFJS.getDocument(vm.pdfurl).then(function (pdfDoc_) { // 初始化pdf vm.pdfDoc = pdfDoc_ vm.page_count = vm.pdfDoc.numPages vm.renderPage(vm.pageNum) }) } } </script> <style lang="stylus" scoped> .cpdf { display: flex; justify-content: center; align-items: center; .center { text-align: center; height: 100%; overflow: hidden; padding-top: 20px; .contor { position: fixed; bottom: 30px; left: 0; width: 100%; z-index: 99999; font-size 30px margin-top 20px margin-bottom: 10px; } } } </style> 复制代码
3、直接当成组件,引用就可以了
import cdpdf from '../../../components/pdf.vue' <cdpdf :pdfurl="pdfurl"></cdpdf> 复制代码
一开始项目使用的是pdf-dist,因为后来电子签章显示不出来:
Warning: Unimplemented widget field type "Sig", falling back to base field type. 复制代码
从网上搜了很多方法,说是需要修改pdf.work.js的源码,全局搜索AnnotationFlag.HIDDEN:
if(data.fieldType==='Sig') { warn('unimplemented annotation type: Widget signature'); // 注释下面这行代码 this.setFlags(AnnotationFlag.HIDDEN); } 复制代码
可能是移动端使用微信浏览器的原因,注释掉代码还是不好使,只能再想其他办法了
三、pdf.js
最后用了最笨的办法,直接从GitHub拉下来pdf.js的demo,用iframe标签包住demo里的HTML文件,直接套着用,完美解决电子签章的问题:
1、从GitHub拉一下源码,或者从这个地址直接下载
mozilla.github.io/pdf.js/gett…
下载下来以后放在public文件下(3.x脚手架)
2、iframe标签直接粗暴的设置src
<iframe :src="pdfUrl" :style="{height: Height}" style="width: 100%"></iframe> this.pdfUrl = '../pdf/web/viewer.html?file=' + this.pdfurl, +'PDF' pdfUrl是iframe标签的URL,pdfurl是需要查看的PDF文件的url 复制代码
总结
只要能实现需求的代码就是好代码,我的项目是移动端查看PDF文件,因为文件上有电子签章,所以尝试了好几种方案,个人还是推荐第二种方案,如果没有电子签章的情况下。
各位哥哥姐姐点个关注吧
这篇关于pdf.js实战,含水印、电子签章解决方案的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-04package.json 文件位置在哪?-icode9专业技术文章分享
- 2024-10-01Craco.js学习:从入门到实践指南
- 2024-10-01Create-React-App学习:入门与实践指南
- 2024-10-01CSS-in-JS学习:从入门到实践指南
- 2024-09-30JSX语法学习:从入门到初步掌握
- 2024-09-30Mock.js学习:入门教程与实战演练
- 2024-09-30React Hooks学习:从入门到实践
- 2024-09-30受控组件学习:React中的基础入门教程
- 2024-09-29JS定时器教程:初学者必看指南
- 2024-09-29JS对象教程:初学者的全面指南