一、背景

记录一下在开发pdf文件预览时遇到的问题,主要是水印和电子签章问题。由于网上也查了不了方案,但解决方案都不适用在生产环境,所以决定贴一下自己的方案。

二、方案介绍

目前主流的移动端pdf文件预览库都是基于mozilla的pdf.js,本文要介绍的两个库也不例外,分别是react的react-pdf和vue的vue-pdf。

闲话少说,直接上代码

1.react-pdf方案,以下代码就完成一个pdf的预览组件了

import { Document, Page } from 'react-pdf';

export default function PdfPreview({ fileUrl }: Props) {

const [numPages, setNumPages] = React.useState(null);

function onDocumentLoadSuccess(document) {

const { numPages } = document;

setNumPages(numPages);

}

return (

file={fileUrl}

onLoadSuccess={onDocumentLoadSuccess}

loading="意向书加载中..."

>

{

Array.from(

new Array(numPages),

(el, index) => (

key={`page_${index + 1}`}

pageNumber={index + 1}

/>

),

)

}

)

}

复制代码

2.vue-pdf方案

v-for="i in numPages"

:key="i"

:src="src"

:page="i"

>

import pdf from 'vue-pdf'

export default {

components: { pdf },

data() {

return {

src: pdfUrl,

numPages: undefined,

}

},

mounted() {

this.src.promise.then(pdf=>{

this.numPages = pdf.numPages;

}).catch(err=>{

console.log('err',err);

}

},

}

复制代码

上面两种方案就能完成基本的多页pdf文件在线预览了,美中不足的是当pdf文件中想添加水印和电子章时满足不了,特别是对于一些交易场景或者电子合同场景。如果你默认使用了水印和电子签章,在控制台会看到有这样的warning

Warning: Unimplemented widget field type "Sig", falling back to base field type. pdf.js:581 和 Warning: Error during font loading: The CMap "baseUrl" parameter must be specified, ensure that the "cMapUrl" and "cMapPacked" API parameters are provided.

第一个warning报的是关于电子签章的问题,第二个warning报的是水印的问题,带着这两个问题去搜索引擎一搜,会有很多的结果,循着这些提示,你翻到这两个库的源码及库依赖的pdfjs-dist源码,然后你会发现,签章的问题是因为下面这一段代码

if (data.fieldType === 'Sig') {

data.fieldValue = null;

_this3.setFlags(_util.AnnotationFlag.HIDDEN);

}

复制代码

注释掉,电子章就正常出来了,这个方法对react-pdf和vue-pdf库都有效,但隐隐感觉那里不对,注释掉的是本地的代码,生产环境怎么办?且看下文。

而水印的问题是因为这两个库中的字体文件(pdfjs-dist/cmaps)在webpack打包后并不会被打包进来(react-pdf和vue-pdf的情况还不一样,下面会补充)。解决方案也很简单,一种是通过webpack的方式把字体文件打包到静态文件中,并引入;另一种是直接引入对应字体文件的cdn地址,或官方提供的https://unpkg.com/pdfjs-dist@2.0.943/cmaps/,代码如下(只截取部分,其余部分和上面的代码相同):

react-pdf

file={fileUrl}

onLoadSuccess={onDocumentLoadSuccess}

loading="意向书加载中..."

options={{

cMapUrl: 'https://unpkg.com/pdfjs-dist@2.0.943/cmaps/',

cMapPacked: true,

}}

>

复制代码

如果你用的是vue,到这里你会发现vue-pdf没提供类似的方法,哭...不管怎样,薪水得拿,需求就要解决,于是你从githug上的readme文档中的api区域发现有这样的字眼,PDFJS.getDocument().带着好奇和编码的直觉,你觉得需要点进去看看,然后发现这个方法里有很多的参数,其中一个和字体相关,即:

/*

* @property {Object} CMapReaderFactory - (optional) The factory that will be

* used when reading built-in CMap files. Providing a custom factory is useful

* for environments without `XMLHttpRequest` support, such as e.g. Node.js.

* The default value is {DOMCMapReaderFactory}.

*/

复制代码

然后结合网上看到的蛛丝马迹,vue-pdf库下的水印问题也愉快解决了,上代码:

import CMapReaderFactory from 'vue-pdf/src/CMapReaderFactory.js'

data() {

return {

src: pdf.createLoadingTask(

{

url: pdfUrl,

CMapReaderFactory,

}

),

}

},

复制代码

如图(水印已经显示出来了,红色标注是打码):

到这里,水印是解决了,签章呢...革命尚未成功,同志仍需要努力,继续雄起coding...

三、终章

关于签章,注释库源码是行不通了,但是显然得通过注释掉对应的代码,去看mozillia/pdfjs的issue,也说了,出于一些原因将签章功能屏蔽了,所以我们的方法也是注释代码,只是换一种方法,将库依赖的部分代码抽出来,注释后再行引用,比如上传cdn后再引用这部分代码。巧的是,react-pdf留有这样的口子,用以引用相应的代码,如下:

import { Document, Page, pdfjs } from 'react-pdf';

pdfjs.GlobalWorkerOptions.workerSrc = 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.0.943/build/pdf.worker.min.js';

复制代码

从react-pdf中多import一个pdfjs,然后换上自己注释掉以下代码的worker.js

if (data.fieldType === 'Sig') {

data.fieldValue = null;

_this3.setFlags(_util.AnnotationFlag.HIDDEN);

}

复制代码

上面的cdn地址 worker.min.js是我贴的一个例子代码,是没有注释掉这部分代码的,有需要的同学自己去github上下载并自行去掉相应代码,有一个注意点就是用的pdfjs-dist和pdf.worker.min.js的版本最好一致,不然可能出现pdf文件不出来的问题,到这react-pdf的pdf文件预览水印和签章就完美解决了。等等,还有一个vue-pdf...

前方的坑虽然太凄迷,请在笑容里为我祝福...

vue-pdf默认只导出了pdf,也就是

import pdf from 'vue-pdf'

复制代码

没有react-pdf那样的口子,可以通过workSrc来修改worker.js,从FJS.getDocument().方法里有看到PDFWorker这样的参数,可以像上面CMapReaderFactory那样传入,但是没搞定这部分,有搞定的同学欢迎分享一下

* @property {PDFWorker} worker - The worker that will be used for the loading

* and parsing of the PDF data.

复制代码

只能另寻他路...还真给我找到了,话不多说,上代码:

import PDFJS from 'pdfjs-dist';

PDFJS.GlobalWorkerOptions.workerSrc = 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.0.943/build/pdf.worker.min.js';

//请注意,这里的cdn worker地址是贴的网上的,并且签章那部分代码是没有注释的,直接拿去用是达不到效果的,我也没有现成的资源可提供,只是贴一下方法

export default {

data() {

return {

pdfDoc: null,

pages: 0,

}

},

methods: {

_renderPage (num) {

this.pdfDoc.getPage(num).then((page) => {

let canvas = document.getElementById('the-canvas' + num)

let ctx = canvas.getContext('2d');

ctx.mozImageSmoothingEnabled = false;

ctx.webkitImageSmoothingEnabled = false;

ctx.msImageSmoothingEnabled = false;

ctx.imageSmoothingEnabled = false;

let dpr = window.devicePixelRatio || 1

let bsr = ctx.webkitBackingStorePixelRatio ||

ctx.mozBackingStorePixelRatio ||

ctx.msBackingStorePixelRatio ||

ctx.oBackingStorePixelRatio ||

ctx.backingStorePixelRatio || 1

let ratio = dpr / bsr

let viewport = page.getViewport(screen.availWidth / page.getViewport(1).width);//这是让pdf文件的大小等于视口的大小

canvas.width = viewport.width * ratio

canvas.height = viewport.height * ratio//这里会进行压缩,解决模糊问题

canvas.style.width = viewport.width + 'px'

canvas.style.height = viewport.height + 'px'

let renderContext = {

canvasContext: ctx,

viewport: viewport,

transform: [ratio, 0, 0, ratio, 0, 0]//这里会进行放大,解决模糊问题

}

page.render(renderContext);

if (this.pages > num) {

this._renderPage(num + 1)

}

})

},

_loadFile (url) {

PDFJS.getDocument({

url,

cMapUrl: 'http://cdn/fonts/cmaps/',//这里同样要引入字体解决水印问题,需自己提供

cMapPacked: true

}).promise.then((pdf) => {

this.pdfDoc = pdf

this.pages = this.pdfDoc.numPages

this.$nextTick(() => {

this._renderPage(1)

})

})

}

},

mounted() {

this._loadFile(pdfUrl);

}

}

复制代码

四、总结

夜深了,想说的都在上面代码里了。简单来说这是一篇踩坑贴,由于自己在解决pdf预览问题时花了不少时间,因此总结梳理出来,希望有遇到相同问题的同学,能从此文得到一些帮助。

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[移动端pdf预览-水印&电子签章问题]http://www.zyiz.net/tech/detail-129606.html

html预览pdf上的电子印章,移动端pdf预览-水印电子签章问题相关推荐

  1. html预览pdf上的电子印章,移动端在线预览pdf显示签名签章pdf显示多页

    效果如图,可显示多页pdf,可显示签章,在移动设备也一样 Document .lightbox{ position: fixed; top: 0px; left: 0px; height: 100%; ...

  2. java 上传文件及预览_SpringBoot上传下载文件及在线预览

    SpringBoot上传下载文件及在线预览 今天大概就说说如何使用SpringBoot进行上传和下载以及在线预览文件 本篇主要介绍上传下载的功能,对于界面就简单一点,大致如下: 一.老规矩还是先看看小 ...

  3. 如何在pdf上编辑文字,分享一种小技巧

    如何在PDF上编辑文字呢?PDF文件是安全性比较比较高的一种文件,使用的人也是比较多的,但是想要直接在PDF上编辑文字也是很难得,这个时候我们就可以使用迅捷PDF编辑器来编辑PDF上的文字,下面小编就 ...

  4. 如何在PDF上编辑文字?手机也能简单编辑

    小伙伴们经常接触PDF文件吗?相信大家都应该知道PDF文件的安全性很高,不容易修改.一个比较重要的文件,通常会选择将其保存为PDF格式.因此,PDF也经常用于一些办公文件,如说明书.合同等.但是当我们 ...

  5. 怎么编辑pdf文件,在pdf上修改文字

    目前办公中一些文档文件主要还是以office类型的文档为主,而pdf文件则不那么常见,所以大家对这种文件都不是很了解.在遇到这种文档需要编辑操作的时候不知道怎样处理.接下来就讲讲怎么编辑pdf文件,在 ...

  6. Office文档上传后实时转换为PDF格式_图片文件上传后实时裁剪_实现在线预览Office文档

    Office文档上传后实时转换为PDF格式_图片文件上传后实时裁剪 前置条件 安装LibreOffice 安装OpenOffice 安装Unoconv 安装ImageMagick.x86_64 安装G ...

  7. 怎样使用Mac的预览应用在PDF上签名?

    如何在PDF上签名?首先想到的是先把文件打印出来,等签完名字后再扫描进电脑里,听起来就很麻烦,现在用Mac的预览应用就可以跳过打印的步骤,轻松完成签名. 用Mac的预览应用在PDF上签名具体步骤 当你 ...

  8. vue3 el-upload 上传附件及预览 限制只能上传一个图片或者pdf格式的文件

    vue3 el-upload 上传附件及预览 限制只能上传一个图片或者pdf格式的文件 效果如图 直接看代码吧 template部分 <div class="file-upload&q ...

  9. 通过Java组件iText生成PDF报表或合同,完成pdf上传,预览,存入数据库

    因业务需要,做了一个通过Java组件iText生成PDF合同,运行成功了,做个记录,也分享给大家. 首先,我们需要准备好一个有文本域的pdf文件. 1.先用word做出你需要的模板,并保存. 2.通过 ...

  10. 手机端html5展示pdf,pdf.js移动端展示预览打开pdf-pdfh5.js

    pdf.js移动端展示预览打开pdf-pdfh5.js 本插件基于pdf.js和jQuery,可手势捏合缩放,支持懒加载(即分段加载). 2019.07.18更新:增加npm install pdfh ...

最新文章

  1. PHP 真正多线程的使用
  2. 基于用户投票的排名算法(五):威尔逊区间
  3. M4i—下一代高速数据采集、数字化仪平台
  4. 复习知识点:UITableView和UICollectionView的常用属性
  5. Spring– DAO和服务层
  6. pxe安装linux后命令不可用,pxe自动安装linux
  7. python 3中 的subprocess
  8. 如何阻止复制剪切和粘贴事件
  9. nginx 安装_Nginx 安装
  10. mysql数据库诊断_MySQL数据库诊断——InnoDB关机问题 【转】
  11. css垂直居中怎么设置?文字上下居中和图片垂直居中
  12. iOS学习——UITableViewCell两种重用方法的区别
  13. 《OSPF和IS-IS详解》
  14. arpg网页游戏之地图(二)
  15. GoldWave的消音、淡入淡出、改变音乐速率
  16. oracle 表复制 long,关于oracle的数据库的数据Long和Number的转化字段
  17. android APP 跳转到应用商店评分
  18. arthes—线上debug好帮手
  19. 张宏 :移动机器人全局定位技术与方法是啥?道翰天琼认知智能机器人平台API接口大脑为您揭秘。
  20. bat 切换网络适配器_Windows批处理自动切换IP地址设置无线网络和以太网的IP地址...

热门文章

  1. 用计算机弹极乐净土谱,极乐净土计算器谱子
  2. 启用计算机并口,电脑并口被禁用怎么办
  3. Python函数练习题
  4. PS2模拟器 PCSX2 新手向
  5. VS2010使用c++、gSOAP调用WebService 图文教程
  6. 给机器学习面试者的十项建议 | 面试官角度
  7. 深入理解“智慧城市”
  8. 官方下载weka,亲测可用!
  9. Android学习路线指南-------任玉刚
  10. clustalw序列比对_CLUSTALW(muscle序列比对)