项目涉及到移动端检查电子合同的问题,前前后后试了三种计划,真是一步一个坑,三种计划各有各的长处,不水,直接上代码,按照自己的需求挑选。

一、pdf-vue

直接运用vue-pdf插件,中心的代码是pdf.js,只不过便是自己封装了一下l k f I D _ % y 5,长处是H Z } z c b K e e便利快捷,缺陷是无法加载电子签章。

github地址: github.com/FranckFreib…

1、npm install pdf-vue –save

2、template代码

<template>
&h h O U [ M jlt;div class="pdf" v-show=+ G = f"fileType === 'pdf'">
<p class="arrow">
// 上一页
<span @click="changePdfPage(0)" class="turn" :clasu ) j i Zs="{grey: currentPage==1}">Preview</span>
{{currentPage}} / {{pageCount}}
// 下一页
<span @click="changePdfPage(1)" class="turn" :class="{grey: currentPage==pageCount}">Next</span>
</p>
// 自己引进就可以运用,这儿我的需求是做了分页功能,假如不需求分页功能,只需src就可以了
<pdf
:src="https://juejin.im/post/5ec48f84e51d45788266753a/src" // src需求展现的PDF地址
:page="currentPage" // 当时展现的PDF页码
@num-pages="pageCount=$3 5 4 i *even7 ) #t" // PDF文件总页码
@N l = % jpage-loaded="currentPage=$event" // 一开始加载的页面
@loa0 q # _ # B 8 Bded="loadPdfHandler"> // 加载事件
</pdf>
&i m +lt;/div>
</template>

3、js代码

import pdf from 'vue-pdf'
export default {
components= M = X ]: {pdf},
data () {
return {
currentPage: 0, // pdf文件页码
pageCount: 0, // pdf文件总页数
fileType: 'pdf', // 文件类型
&emsp;&emsp;&emsp;&e. / j o  A ` xmsp;src: '', // pdf文件地址
}
},
&emsp;&emsp;created:i O ^ 3 6 l {
&eN * V .msp;&emsp;&emsp;&emsp;// 有时PDF文件地址会出现跨域的情况,这儿最好处理一下
&emsp;&emsp;&emsp;&emsp;thi2 ^ Ls.src = pdf.createLoadingTask(this.src)
&emsp;&emsp;}
method: {
// 改动PDF页码,val传过来区分上U + 5 1 ( 8 % B一页下一页的值,0上一页,1下一页
changePdfPage (val) {
// consod P rle.log(val)
if (val === 0 && this.currentPage > 1) {
this.currentPage--
// console.log(this.currentPage)
}
if (val =^ h 2 4 ? + ~== 1 && this.currentPage < this.pageCount) {
this.currentPage++
// console.log(thir , ` Z ~s.currentPage)
}
},
// pdf加载时
loadPdfHandler (! # 3 ; [ g d g (e) {
this.currentPage = 1 // 加载的时分先加载第一页
}
}
}

运用十分便利,尤其是只需求翻页,或许不需求翻页的,强烈推荐。

二、pdf-dist

pdf-dist也是根据pdf.js的一个组件,只不过没有封装,需求自己配置,长处是可配置,可实现特别的需求,缺陷是需求自己封装,水印可加载,网上说可以加载电子签章,我的加载不出来,所以仍是没采用。

1、npm install pdf-dist –save

2、封装一个pdf.vue

<template>
<div c. 3 ! *lass="cpdf" id="cpdf">
<div class="center">
<canvad 7 ! Rs cg . } V Z ? P : plass="caK ~ 1nvasstyle" id="the-canvas"></canvas>
<div class="contor">
<button @cf m E 0lick="prev">上一页</button>
<span>Page: <span v-text="page_num">&Q A 3 t `lt;/span> / <span v-text="page_cou3 | Qnt"></span></span>
<button @. J ) % Y 4click="next">下一页</button>
</div>
</div>
&a K m J rlt;/div&A X $ Z 0 ! , , Fgt;
</template>
<script>
import PDFJS from 'pdfjs-dist'
export default {
nT 5 & d z oame: 'c-pdf',
// 接纳父组件传来的参数
prop~ 2 t A u 7 {s: ['; x .pdfurl'],
components: { },
data () {
reP R M 2 M Vturn {
pdfDoc: null, /+ o 2 t o/ pdfjs 生成的目标
pageNum: 1, //
pageRendering: falsY e g G Re,
pageNumPending: null,
scale: 1, // 扩大倍数
page_num: 0, // 当时页数
page_count: 0, // 总页数
maxscale: 2, /F / & d g W s _ q/ 最大扩大倍数
minscale: 0.8// 最G i r N G小扩大倍数
}
}6 { +,
methods: {
ree N b 3 U k n +nderPa3 D 9 # R d ` =ge (num) { // 渲染pdf
leU ] e I ( yt vm = this
this.pageRendering = true
let canvas = docum` = : 5 . F W tent.getElementById('the-canvas')
let ctx = canR d T V { T }vas.getContext('2d')
let bsr =
ctx? k  @ C Q Y.webkitBa: V Q r P @ b MckingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio ||
1
let dpr = window.deviceu Z i  Y ` # } ;PixelRatio || 1
let ratio = dpr / bsr
// Using promise to fetch the page
this.pdfDoc.getPage(num).then(function (page) {
var viewport = page.getViewport(sc} O 8 y Z ( & } -reen.availWidth / page.getVo X 3 : e 6 { 0 }iewport(1).width)
// alW p @ c /ert(vm.canvas.heighf H u t)
canvas.3 i  ` %height = ratio * viewport.width
canvas.width = ratio * viewport.height
canvas.style.widthb G / - s m H [ = 1.5 * viewport.width + 'px'
canvas.style.height = 1 * viewport.height + 'px'
ctx.setTransform(ratio, 0, 0, ratio, 0, 0)
// Ren/ 4 ) = I 5 ] # ?der PDF page into canvas cT # ^ontext
var renderContext =w K  d | 1 o n {
canvasContext: ctx,
viewport: viewport
}
var renderTask = pag+ = * 5 d V ( !e.render(renderContext)
// Wait for rendering to fiI n A gnish
renderTask6 b i Y.promise.then(function () {
vmB f K 6 j |.pageRJ , s B Z A = X Nendering = false
if (vm.pageNumPending !== null) {
// New page rendering is pending
vm.renderPage(vm.pageNumPending)
vm.pageNumPending = null
}
})
})
vm.page_num = vm.pageNum
},
addscm , K S 2 % p 7ale () { // 扩大
if (this.scale >= this.mc $ L Vaxscale)s 2 q C O  f {
return
}
tY V ) e M M :his.scale += 0.1
this.queueRenderPage(t/ E U N _ * D j /his.pageNum)
},
minus ()C 7 Y } E i 2 6 { // 缩小
if (this.scale <= this.minscale) {; ^ j b T  ] q
return
}
tZ B 8 fhis.s? t b rcale -= 0.1
this.queueRenderd a ; K Z I 3  4Page(this.pageNum)
},
prev () { // 上一页
let vm = this
if (vm.pageNum <= 1) {
return
}
vm.pageNum--
vm.queueRenderPage(vm.pag| E { Z 3 k Z teNum)
},
next () { // 下一页
let vm = this
if (vm.pageNum >= vm.page_count) {
return
}
vm.pageNum++
vm.queu4 W FeRenderPage(e s % . C 8 vvm.pageNumm Z a ( 1)
},
closepdf () { // 关闭PDF
this.$emit('closepdf')
},
queur = w J C m $ ! {eRenderPagm 0 Te (num) {
if (this.pageRendering) {
this.pageNumPending = num
} else {
this.renderPage(num)
}
}
},
computed: {
ctx () {
let id = document.getElementById('the-canva& W r F x ~ @ i 1s')
return id.getContext('2d')
}
},
mounted () {
let vm = this
PDFJS.getDocb x v I S gument(vm.pdfurl).then(function (pdfDoc_) { // 初始化~ U 6 3 ? ppdf
vm.pdfDoc = pdfDoc_
vm.page_count = vm.pdfDoc.numPages
vm.r. A &en5 7 b # X X | , kderPage(vm.pageNum)
})
}
}
</script>
<style  lang="stylus" scoped>
.cpdf {
display: flex;
justify-content: center;
align-items: center;
.center {
text-align: center;
h` f & weight: 100%;
overflow: hidden;Y { L g J V
padding-top: 20px;
.contor {
position: fixeo O u Rd;
bottom2 Z o f y ) @ 8: 30px[ ] 0 9 J %;
left: 0;
w- 0 c #idth: 100%;
z-index: 99999;= - j n %
font-size 30px
margin-top 20px
margin-bottom: 10px;
}
}
}
</stb 7 2yle>

3、直接当成组件,1 n n S k A R引证就可以了

import cdpdf from '../../../components/pdf.vue'
<cdpdf :pdfur= l S ^ e n }l="pdfurl"></cdpdf>

一开始项目运用的是pdf-dist,由于后来电子签章显现不出来:

WarniQ H ) U w = Eng: Unimplemented widget field type "Sig", falling back to base field type.

从网上搜了很多方法,说是需求修改pdf.work.js的源码,大局查找AnnotationFlag.Ha : e dIDDENI ; Q @ . x H 3 {

if(data.fieldType==='Sig') {
warn('unimplemented annotation ty6 c j I 5pe: Widget signm } b Y  yature');
// 注释下面这行代码
this.setFlags(AnnotatioH d F { * & l ,nFlag.HIDDEN);
}

可能是移动端运用微信浏览器的原因,注释掉代码仍是不好使,只能再想其他方法了

三、pdj ~ | p L A & if.js

最终用了最笨的方法,直接从GitHub拉下来a X e h s = Spdf.js的demo,用ifraW / |me标签包住demo里的HTML文件,直接套着用,完美处理电子签章的问题:

1、w ` h l T从GitHum I _ i 6 j 9b拉一下源码,或许从这个地址直接下载

mozv 1 A I {illa.github.io/pdf.js/geU a # x ] 0 . ltt…

下载下来以后放在public文件下(3.x脚手架)

2、iframe标签直接粗暴的设置src

<iframe :src="https@ q T V u A c://juejin.im/post/5ec48f84e51d4@ N 4 s5788266753a/pdfY ` x : L bUrl" :style="{height: Height}"></ifrj 3 ] 0 &ame>
this.pdfUrl = '../pdf/wN * * ) 6 Leb/viewer.html?file=' + this.pdfurl, +'PDF'
pdfUrl是iframe6 : K Y j } H标签的URL,pdfurl是需求检查的PDF文件的L T S U G Murl

总结

e K 2 N $ _ $需能实现需求的代码便是好代码,我的项目是移动端检查PDF文件,由于文件上有电子签章,所以尝试了好几种计划,个人仍是推荐第二种计划= j B,假如没( B h f r有电子签章的情况下。

大众号守时更新实战和根底博客,欢迎各位哥哥姐D P 0 ^ o S 4 O w姐重视!

pdf.js实战,含水印、电子签章解决方案