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

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

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

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

一、利用iframe

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

<iframe src="Url" style="width:100%;height:100%" frameborder="0"></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,
},
第三步 使用
<VuePdf  src="PDFurl" : />
上面是最简单的使用方式,只能显示第一页的pdf,满足不了大部分需求,现在增加功能模板里
<VuePdf  v-for="i in numPages" :key="i" :src="url" :page="i" />
下面方法在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下载

<div @click="down(pdfName)">下载</div>
//需要两个参数 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来直接跳转的形式来显示

<iframe  :src="iframeUrl" frameborder="0"></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页,不然会加载时间过长导致打不开。

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

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

  1. pdf预览在vue项目中的使用兼容ie浏览器

    最近做项目有需求需要pdf在线预览并支持下载,而且还要兼容ie浏览器,之前又是使用过vue-pdf插件在chrome上没有问题但是在ie上不兼容.最后使用了pdf.Js这个原生库,虽然网上有许多使用教 ...

  2. 纯前端下载pdf链接文件,而不是打开预览的解决方案

    纯前端下载pdf链接文件,而不是打开预览的解决方案 参考文章: (1)纯前端下载pdf链接文件,而不是打开预览的解决方案 (2)https://www.cnblogs.com/jackson-yqj/ ...

  3. vue3 - 【完整源码】超详细实现网站 / H5 在线预览 pdf 文件功能,支持缩放、旋转、全屏预览、打印、下载、内容检索、主题色定制、侧边缩略图、页码跳转等等(最好用的pdf预览器,注释详细!)

    效果图 在 Vue3.js 项目中,实现了快速高效的 pdf 预览器工具组件,附带详细的使用教程与详细的注释,保证一键复制轻松搞定! 详细的注释很容易二次修改,很多实用功能,你也可以自定义界面上的样式 ...

  4. PDF 预览和下载你是怎么实现的?

    在开发过程中要求对 PDF 类型的发票提供 预览 和 下载 功能,**PDF** 类型文件的来源又包括 H5 移动端 和 **PC 端**,而针对这两个不同端的处理会有些许不同,下文会有所提及. 针对 ...

  5. pdfh5.js 基于pdf.js和jQuery,web/h5/移动端PDF预览手势缩放插件。

    pdfh5.js 基于pdf.js和jQuery,web/h5/移动端PDF预览手势缩放插件. 注意:本地绝对路径地址不能加载,跨域问题用代理或者服务端解决. svg模式渲染存在缺陷,只能渲染普通pd ...

  6. 文档在线预览产品系列-解决方案篇

    文档在线预览产品系列-解决方案篇 hello 大家好,我又来了,上次我们聊到文档在线预览市场的产品类别有很多,今天我们就来盘点下各个类别以及对应的一些产品品牌. 产品类别 开源项目 开源项目是啥就不多 ...

  7. 前端实现 PDF 预览的常见方案

    前端实现 PDF 预览的常见方案 由于在搭建个人博客时,想实现在线预览 pdf 格式的个人简历,经过查阅大致有三大类实现方案:本文共涉及以下 5 种实现方案,如下所示: 使用 HTML 标签 ifra ...

  8. 实现微信小程序和手机app(基于vue)PDF预览功能

    引言:最近在做微信小程序和手机端app开发(基于vue),实现一个pdf预览功能. 需求:点击pdf列表,跳转到预览pdf页面,页面上强制阅读10s后,显示一个按钮返回,更新阅读状态: 要求:不能调用 ...

  9. 实现Vue移动端的PDF预览

    最近做到一个功能,PDF预览:这个功能看着蛮简单的,结果搞了两个下午,真是欲哭无泪.记录一下所查到的预览方法. 我在网上找了蛮多教程的,大致都是以下几个方法实现预览: 使用 iframe 标签 使用 ...

最新文章

  1. 前端新手学习记录2 -使用vscode编写个人网站首页
  2. 痛入爽出 HTTP/2:代码实战1
  3. html权重值_HTML标签权重分值排列
  4. Matlab画图小结(二)
  5. scrapy-redis 分布式哔哩哔哩网站用户爬虫
  6. java class 转 字节_[转]JAVA字节数据与JAVA类型的转换
  7. 14年百度深度学习校招题目
  8. 已知三个用不同数制表示的整数_数学一轮复习26,数列的概念及简单表示法,常用方法及具体策略...
  9. Leedcode1-求树的最小高度
  10. c语言求前15项中偶数项的和,偶数前n项和
  11. res.data.data_在Data.gov进行幕后推销
  12. PAT乙级(1014 福尔摩斯的约会)
  13. Redis09-集群相关笔记
  14. Sublime Text 3的中文显示乱码问题
  15. Cocos2d-x一张小背景重复贴图充满整个屏幕
  16. Hadoop序列化及案例
  17. 使用MSHTML解析HTML页面
  18. 从精彩阅读网上爬取《凡人修仙传》
  19. javascript学习-SVG
  20. 计算机专业要学英语口语,学习英语口语必须掌握两大法宝

热门文章

  1. 数值分析 三次样条插值及实现
  2. Cython入门到放弃(一)
  3. Excel VBA:设置单元格边框
  4. (C++/python)LeetCode 589. N叉树的前序遍历
  5. oracle+dbcc+checkdb,dbcc checkdb 修复数据库
  6. 【评测】一种组织蛋白快速提取方法
  7. python的Gensim库如何使用
  8. CNN Application
  9. 201609-3 炉石传说
  10. Java 操作Word表格——创建嵌套表格、添加/复制表格行或列、设置表格是否禁止跨页断行