首页 >> 大全

工作学习总结-pdf.js的踩坑和运用

2023-09-03 大全 36 作者:考证青年

周末了,终于有这么一整段的时间去总结整理了,这个月很忙,需求很多,年龄不小了,生活中个人的事情也不少。时间是最公平的,因为每个人每天都是过这么长时间,好好珍惜每一分。好了,不感慨了。进入正题吧。

先说一下项目结构:.0 + .0 这个月做了一个pdf展示的需求,后台小伙伴传过来一个pdf格式的url,

这个url长这样:

url = ”https://sg.ibs.baidu.com.cn/download/fla-ybkj-dmz-dev-pri/24a1bed5f3fc46d582d6ff7747445b14?attname=BS012LYT.pdf"

其实就是一个pdf格式的文件的url地址,然后前端展示一下。原本以为实现会很简单,没想坑是一个接一个,下面来一一说一下吧。

1.先把后台传过来的url做一下转化,在中的转化如下:

 html的代码ts中的代码this.url = this.sanitizer.bypassSecurityTrustResourceUrl("assets/viewer/web/viewer.html?file=" + encodeURIComponent(res.data.url));

只有转化之后的url加载到中才有效

2.这个pdf.js是一个泛称,装上之后,会有这么多文件,如图:

html页面中写法如下:



其中

属性规定是否在 中显示滚动条。有三个值 yes 、no、 auto

属性规定 看上去像是包含文档的一部分。

是监听ion- 内容的滚动事件。然后就开始在里面增加滚动后的触发事件了,代码如下:

scrollEvent(event) {this.show = true;let het1 = document.body.clientHeight;let het2 = document.getElementById("deatilShow").clientHeight; this.ngzone.run(() => {let top = event.scrollTop; if (het2 <= het1 + top) {this.buttonShow = false;}})}

上面代码中的this..run()的用法请见我的另外一篇文章工作学习总结–中的的简单使用

当我滚动页面的时候,事件却没有触发,因为我滚动的是页面,也就是嵌入的另外一个页面,所以不会触发事件 。所以我找了一个折中的方案,给加了一个-,当滚动到底部的时候,再往上滑一点,就会触发这个事件了,也就是ion-这个页面滚动了,但是效果不太好,在ios和安卓上体验都不是很好,所以最后也没有采用这种方法。那怎么办呢?

经过自己的搜索+思索和其他小伙伴的帮助,最后还是以一种笨方法解决了。

3.下面描述我探索的过程(探索方法一):

我首先获取这个元素,监听它的滚动事件,获取到的是一个html,如图:

所以给它加滚动事件无效,然后又百度方法,还是没找到有效的方法,最后谷歌了一下,找到了一个方法,就是监听irame中的id为的元素的滚动事件才行,这个id为的元素其实就是.html中的一个元素,所有pdf文件页面都加载到它里面,它在.html中的代码如下:

然后就去获取这个元素

        setTimeout(() => {if(this.elementRef.nativeElement.querySelector('.scroll-content #deatilShow') && this.elementRef.nativeElement.querySelector('.scroll-content #deatilShow').contentDocument && this.elementRef.nativeElement.querySelector('.scroll-content #deatilShow').contentDocument.getElementById("viewerContainer")) {clearInterval(this.timer)viewerContainer = this.elementRef.nativeElement.querySelector('.scroll-content #deatilShow').contentDocument.getElementById("viewerContainer");viewerContainer.addEventListener('scroll',(event) => {let scrollTop = event.target.scrollTop ;let clientHeight = event.target.clientHeight ;let scrollHeight = event.target.scrollHeight ;if(scrollTop+clientHeight == scrollHeight){// 添加滚到底部要处理的事件}});}},2000)

为什么加个定时器呢?是因为网速不好的时候,pdf加载很慢,有可能页面还没加载完全,可能这个时候获取不到元素。这个时候在浏览器上跑的时候报跨域的问题,所以在谷歌浏览器设置了一下跨域。这个时候页面上事件都是可以的,都可以触发了。然后打包在ios和安卓手机上测的时候无效,一点效果没有,这个时候就纳闷了。为什么呢?手机连着电脑调试了一下,发现还是这个元素没有获取到。查了一下,猜测应该是pdf.js安全策略,不让外界获取这个元素,因为pdf文件都加载到这个元素下面,怕外界对pdf文件进行修改操作。那电脑上为什么可以呢,也许是因为给谷歌设置了跨域,可以忽略这个风险,具体原因还需后续再仔细去查一下。这个方法又被pass掉了,继续想办法吧

4.探索方法二

获取不到这个元素就没有办法监听它的滚动事件。那既然外界获取不到,我就在.html中获取这个元素,并给它监听这个滚动事件。先试一下,试试又不花钱。

于是我在.html中给它加了这样一段代码


然后在页面上监听发出的事件就可以了

ngOnInit() {window.addEventListener("message",(event)=>{event.data.toBottom?this.show = true:"";event.data.scrolled?this.button = true:"";})}

踩坑指南__踩坑经验

问题总算解决了,但是这也只是一个临时的方案,后期如果有什么更好的方法还要去优化的。

这个方法中有两个问题需要注意一下,一个是在.html页面中用 ..发出消息,另外就是在父页面进行监听的时候,用event.data的数据来区分监听是哪种消息。

5.最后说一下我对pdfjs这块的源码做了哪些改动

第一点:我注释掉了跨域这一块,在.js里面(在1751行到1753行)

 try {var viewerOrigin = new _pdfjsLib.URL(window.location.href).origin || 'null';if (HOSTED_VIEWER_ORIGINS.includes(viewerOrigin)) {return;}var _ref8 = new _pdfjsLib.URL(file, window.location.href),origin = _ref8.origin,protocol = _ref8.protocol;// if (origin !== viewerOrigin && protocol !== 'blob:') {//   throw new Error('file origin does not match viewer\'s');// }} catch (ex) {

第二点:需求需要,需要合同文件上展示签章,也就是盖过的章,所以在pdf.work.js里面注释掉这样几行代码

大约注释了四行代码(在28684行到28688行)

 if (!Number.isInteger(data.fieldFlags) || data.fieldFlags < 0) {data.fieldFlags = 0;}data.readOnly = _this2.hasFieldFlag(_util.AnnotationFieldFlag.READONLY);// if (data.fieldType === 'Sig') {//   data.fieldValue = null;//   _this2.setFlags(_util.AnnotationFlag.HIDDEN);// }return _this2;}

我使用的pdf.js是2.0的版本

第三点:清除pdf缓存 为什么说清除pdf缓存呢?例如 我打开一个pdf文件,滑到第6页,然后退出这个页面,再进来还是在第6页。那有没有方法可以让文件从第1页开始加载呢。就开始了我的探索之路,其实开发经验丰富的人,找问题很快也很准,也许是因为开发的需求多了,接触的问题也多了。我先去在插件里面去找,在.js里面找。缓存就是意味着历史记录,于是我先查,我发现了有这样一行代码:

localStorage.setItem('pdfjs.history', databaseStr);

我感觉这就是我要找的,于是我就去浏览器的里面找,果然,请看图:

所以我在.js中的第13457行把它注释掉了

_regenerator.default.mark(function _callee() {var databaseStr;return _regenerator.default.wrap(function _callee$(_context) {while (1) {switch (_context.prev = _context.next) {case 0:databaseStr = JSON.stringify(this.database);// localStorage.setItem('pdfjs.history', databaseStr);  case 2:case "end":return _context.stop();}}}, _callee, this);}));

然后就没有缓存了,问题也解决了。

还有一种笨方法就是在pdf的url后面加一个时间戳或者随机数。

以后关于pdf.js遇到的问题,到时候还会补充。

tags: pdf

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了