PDF预览完整解决方案及各种兼容(VUE版)
创始人
2024-02-14 01:13:06
0

PDF预览完整解决方案及各种兼容(VUE版)

PDF预览完整解决方案及各种兼容(VUE版) - 掘金

前端学习使者正在上传…重新上传取消

2021年11月12日 16:57 ·  阅读 2547

一、利用iframe

就一行代码就够了,只能满足最基本的浏览,且会出现很多问题。


复制代码

**问题一缓存问题:**利用iframe打开pdf后,当再次利用iframe打开另一个pdf时会显示第一份pdf,原因是浏览器对url的缓存处理。

**解决办法:**给url加时间戳或随机数,这样就没有缓存问题了。

    const fresh=new Date().getTime();//时间戳    this.url = this.url+'?'+ fresh; // 初始化查看pdf应用地址
复制代码

**问题二使用base64url问题:**有些pdf的url采用base64格式,直接将base64格式url放进src中可能会报错导致显示不了。原因是base64地址太长,浏览器不支持。

**解决办法:**利用Blob转base64url成文件路径.

  var bstr = window.atob(_this.baseUrl); //解码  var n = bstr.length;  var u8arr = new Uint8Array(n);  while (n--) {  u8arr[n] = bstr.charCodeAt(n); //转二进制  }  let blob = new Blob([u8arr], { type: 'application/pdf' }); //用blob生成pdf文件,返回PDF文件  this.url = window.URL.createObjectURL(blob); //得到的文件路径url
复制代码

**问题三特殊字体和水印无法显示:**这里采用插件的形式解决

二、利用vue-pdf插件

这里以VUE框架为例。vue-pdf是基于pdfjs-dist插件的vue封装。不是vue框架可以去找pdfjs-dist对应的封装或者直接用pdfjs-dist,不过pdfjs-dist使用稍微复杂些。

第一步 安装 npm install --save vue-pdf
第二部引入注册 
import VuePdf from "vue-pdf";
export default {
components: {
VuePdf,
},
第三步 使用

上面是最简单的使用方式,只能显示第一页的pdf,满足不了大部分需求,现在增加功能模板里

下面方法在mounted里面使用// PDF初始化    getNumPages() {      let loadingTask = VuePdf.createLoadingTask(this.url,      );      loadingTask.promise.then(pdf => {        this.numPages = pdf.numPages;      }).catch(err => {        console.error('pdf 加载失败', err);      })    },numPages、url在data里面定义为空,在getNumPages()调用前将路径赋值给this.url
复制代码

这样就可以得到一个可以pdf的全部内容,pdf放大缩小翻页就不赘述了百度很多

PDF下载

下载
//需要两个参数 pdfName 和 pdf的base64地址。 在调用方法前将pdf的base64地址赋值给this.baseUrl就可以调用方法下载。down(pdfName){ const fileName = pdfName; let byteCharacters = atob(this.baseUrl); let byteNumbers = new Array (byteCharacters.length); for (var i = 0; i < byteCharacters.length; i++) { byteNumbers[i] = byteCharacters.charCodeAt(i); } let byteArray = new Uint8Array ( byteNumbers); let blob = new Blob([byteArray], { type:"application/pdf"}); if (navigator.msSaveOrOpenBlob) { navigator.msSaveBlob(blob,fileName); }else{ let link = document.createElement("a"); link.href = window.URL.createObjectURL(blob); link.download = fileName; document.body.appendChild(link); link.click(); document.body.removeChild(link); window.URL.revokeObjectURL(link.href); } }, 复制代码

VUE-PDF出现问题一:部分pdf水印不显示

解决办法
+ 步骤一 在node_modules/pdfjs-dist/build/pdf.worker.js注释掉一行代码
+ if (data.fieldType === "Sig") {
+      data.fieldValue = null;+      // 注释掉底下这行 就可以显示电子签章
+      // this.setFlags(_util.AnnotationFlag.HIDDEN);+ }
+ 步骤二 在node_modules/pdfjs-dist/es5/build/pdf.worker.js注释掉一行代码
+ if (data.fieldType === "Sig") {+    data.fieldValue = null;
+      // 注释掉底下这行 就可以显示电子签章+      // _this4.setFlags(_util.AnnotationFlag.HIDDEN);
+  }
复制代码

问题又来了,在node_modules里面改动文件下一次打包或者项目上线就行不通了。

这里采用把vue-pdf项目文件放在服务器tomcat的一个文件夹下。项目里用iframe来直接跳转的形式来显示

    
const fresh=new Date().getTime();//时间戳    
this.iframeUrl = location.origin + "/pdf/index.html"+'?'+ fresh; // 初始化查看pdf应用地址
复制代码

那么在服务器下的vue-pdf文件如何得到项目上传过来的PDF信息呢,这里采用indexDB数据库。这里不推荐使用cookies和localStorage的形式存储数据,因为PDF数据可能会很大,另外两种形式容量不够。

IndexDB存储PDF需要的信息

     在上线项目里使用/**          *@param url pdf地址          
*@param baseUrl pdfbase64地址          
* @param fileName 文件名          
**/        
setIndexDB(url,baseUrl,fileName){            
// 创建indexDB数据库          //pdfDB          
var request = window.indexedDB.open('pdfData');          
request.onerror = function() {                  
console.log('数据库打开失败');          };            
request.onsuccess = function(e) {              
var pdfDB= e.target.result;              
var store = pdfDB.transaction('workers','readwrite').objectStore('workers');               
store.put({ id: 1, pdfUrl: url,baseUrl:baseUrl,pdfName:fileName});            
};            
request.onupgradeneeded =  function(e){                
// 在数据库中创建该对象空间,workers相当于表的名字                
e.target.result.createObjectStore('workers', {keyPath:'id'});            
}          
},
复制代码

在vue-pdf里面获取存储的数据

    getPdfUrl() {      const _this = this;      const request = window.indexedDB.open("pdfData");      request.onerror = function () {        console.log("数据库打开失败");      };      request.onsuccess = function (e) {        //  var store = e.target.result.transaction('workers','readwrite').objectStore('workers');        //  store.put({id:1,pdfUrl:"2.pdf",pdfName:"",baseUrl:"",pathType:"路径形式"})       const readPDF = e.target.result          .transaction(["workers"])          .objectStore("workers")          .get(1);        readPDF.onsuccess = () => {          if (readPDF.result) {            _this.url = readPDF.result.pdfUrl;            _this.baseUrl = readPDF.result.baseUrl;            _this.pdfName = readPDF.result.pdfName;              var bstr = window.atob(_this.baseUrl); //解码              var n = bstr.length;              var u8arr = new Uint8Array(n);              while (n--) {              u8arr[n] = bstr.charCodeAt(n); //转二进制              }              let blob = new Blob([u8arr], { type: 'application/pdf' }); //用blob生成pdf文件,返回PDF文件              let path = window.URL.createObjectURL(blob);              _this.iframeUrl = path; // 初始化查看pdf应用地址              _this.getNumPages();                      } else {            console.log("未获得数据记录");          }        };      };      request.onupgradeneeded = function (e) {        // 在数据库中创建该对象空间,workers相当于表的名字,表名不可随意更改        e.target.result.createObjectStore("workers", { keyPath: "id" });      };    },
复制代码

具体indexDB看文档www.ruanyifeng.com/blog/2018/0…

vue-pdf项目例子看gitee.com/tianguai/vu…

问题二:字体缺失

VUE-PDF会有一些特殊字体显示不了,这是由于node_modules/pdfjs-dist/cmaps路径下没有对应的字体文件

解决方法:在vue-pdf项目例子中加入以下代码,这里引入外部字体库。

    computed: {pdfSrc(){//处理pdfUrl返回let src =  pdf.createLoadingTask({url: this.pdfUrl,//引入pdf.js字体,templcMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.5.207/cmaps/',cMapPacked: true})return src ;}}
复制代码

但我们公司项目包含了非常多的不同字体,还是满足不了需求,我采用了浏览器默认查看pdf方式和插件方式两种同时使用,可以解决99%的需求啦。不过使用插件形式的pdf不要超过200页,不然会加载时间过长导致打不开。

效果图,哈哈有跟没有一样

相关内容

热门资讯

描写黄河的优美句子 描写黄河的优美句子大全  在日常的学习、工作、生活中,大家都接触过比较经典的句子吧,从句法角度说,句...
唯美快乐幻想的句子精选195... 唯美快乐幻想的句子 精选114句1. 有人用。谁都憧憬过未来的样子吧,就像我,每天闲着没事总是要幻想...
表达道歉的英语句子精选54句 表达道歉的英语句子 精选54句1. A : I'm sorry for last time上次很抱歉...
参加葬礼后的心情句子精选43... 参加葬礼后的心情句子 精选101句1. 我结婚的时侯你一定要来哦,因为看见你我会有安全感。2. 我不...
关于美食的唯美句子   人生的旅途中有太多的岔口,一转身或许就是一辈子。下面是小编为大家整理的关于美食的唯美句子,欢迎欣...
《平凡的世界》好词好句好段摘... 《平凡的世界》好词好句好段摘抄  《平凡的世界》里有一群不平凡的人,是这群不平凡的人组成了这平凡的世...
和老婆说肉麻的语句 和老婆说肉麻的语句  在学习、工作乃至生活中,大家都听说过或者使用过一些比较经典的句子吧,从表达的角...
表现执行力强的句子 表现执行力强的句子(精选60句)  在日常学习、工作或生活中,大家都对那些朗朗上口的句子很是熟悉吧,...
描写秋天的简短句子 描写秋天的简短句子(精选80句)  在生活、工作和学习中,大家都对那些朗朗上口的句子很是熟悉吧,不同...
有坚持道理的句子精选491句 有坚持道理的句子 精选128句1. 滴水穿石,不是因其力量,而是因其坚韧不拔锲而不舍。2. 忍耐和坚...
关于负债累累的句子精选280... 关于负债累累的句子 精选37句1. 智慧课堂|如何以家庭为单位合理购买保险?2. 意识影响思维方式!...
别人骂我偶像我要漂亮的回击句... 别人骂我偶像我要漂亮的回击句子 精选57句1. 生活是无聊的,是需要季节的陪伴。2. 人之所以活的累...
写风景优美的句子精选685句 写风景优美的句子 精选77句1. 在希望的田野上,辛勤耕耘;在希望的田野上,艰苦劳作;在希望的田野上...
身体健康最重要的句子 身体健康最重要的句子  在日常学习、工作抑或是生活中,大家最不陌生的就是句子了吧,句子能表达一个完整...
描写夕阳西下的唯美句子 描写夕阳西下的唯美句子  描写夕阳西下的唯美句子(精选500句)  夕阳的余晖染红了半边天,人们都不...
描写架子鼓表演的句子精选72... 描写架子鼓表演的句子 精选72句1. 爵士鼓不仅有强烈的节奏,且通过两只手和双脚的相互配合,巧妙的演...
描写冬天的优美句子 描写冬天的优美句子53句  “一日之计在于晨”。大家都应该珍惜早晨的这宝贵的时光。你瞧,那些小运动员...
有才华得不到施展句子精选31... 有才华得不到施展句子 精选31句1. 有志无时2. 千里马常有,而伯乐不常有。——韩愈《马说》意思是...
李宗盛最美歌词句子精选250... 李宗盛最美歌词句子 精选59句1. 相爱是容易的,相处是困难的。2. 尘埃落定之后,回忆别来挑拨。—...
夸赞江山句子精选328句 夸赞江山句子 精选40句1. 我心中的黄河是气势磅礴的。“黄河之水天上来,奔流到海不复回。”滚滚黄水...