java pdf如何实现分页返回pdf_如何实现高性能的在线 PDF 预览

本文介绍了如何使用PDF.js库实现分片加载PDF文件,以提高在线预览的性能。通过服务器对PDF文件进行分片,客户端根据用户滚动行为按需下载和渲染指定分片,减少了用户首次打开PDF时的等待时间。此外,还探讨了优化策略,如使用IntersectionObserver API进行滚动加载和页面元素复用,以解决大文件带来的性能问题。
摘要由CSDN通过智能技术生成
c637a63398dc7da754630253198246c0.png

作者:子木 政采云前端团队

转发链接:https://mp.weixin.qq.com/s/Wx_gJLrZftJ_dm2phoUf8g

引言

最近接到产品需求,用户需要在我们可站点上在线查看 PDF 文件,并且查看时,用户可以对 PDF 文件的进行旋转、缩放、跳转到指定页码等操作。

这个太简单了,随便找找就一堆轮子。

目前常见的在线 PDF 查看方案:

  • 使用 iframe、embed、object 标签直接加载

采用此方案,只需要直接将 PDF 的在线地址设置为标签的 src 属性

  • 使用第三方库 PDF.js 加载

这个方案麻烦一点,我们需要在项目中引入 PDF.js 这个库,然后再使用 iframe 来加载指定的 HTML 文件(下文代码中的 viewer.html ),并且将需要访问的 PDF 的在线地址作为参数传递进去。大概就像下面一样:

showPdf (selector, options) {  const { width, height, fileUrl } = options;  this.pdfFrame = document.createElement('iframe');  this.pdfFrame.width = width;  this.pdfFrame.height = height;  this.pdfFrame.src = `./assets/web/viewer.html?file=${encodeURIComponent(fileUrl)}`;  document.getElementById(selector).append(this.pdfFrame);}

这里可能会遇到跨域的问题,不过不是本文重点,不展开讲,相信这种小事难不倒聪明的你。

前面小编也有讲到pdf.js 相关文章:细品pdf.js实践解决含水印、电子签章问题「Vue篇」

于是乎,啪啪啪几行代码迅速搞定给产品演示。然后产品拿了个线上文件来尝试效果。。。

994026fdb83d1477868fe7baff2d72d4.png

两人对着白屏尴尬的沉默良久,产品终于忍不住了。

“这怎么这么慢?不行,用户肯定不能接受。。。”

“公司网络不好... 你这文件太大了... 你重启一下试试?“

不存在的,作为一个优秀的前端开发者,怎么可以说这种话,当然是想办法解决啦。

重新整理一下产品的需求:

  • 页面上查看服务器上的 pdf 文件
  • 支持页码跳转、旋转、缩放
  • 打开要快

基本上前两条上述方案都能满足,所以我们需要解决的关键问题在于如何让用户快速打开内容,减少等待时间。由于现有方案都是将 pdf 文件内容全部下载完成之后才开始进行渲染,如果文件比较大的时候,用户第一次打开时就可能需要等待很长时间。那么思路有了:我们可不可以不下载全部的文件内容就开始渲染?

方案思路 - PDF 内容分片加载

因为用户不可能一眼看到所有的 PDF 内容,每次只能看到屏幕显示范围内的几页。所以我们可以将可视范围内的PDF 页面内容优先下载并展示,可视范围外的我们根据用户浏览的实际位置按需下载和渲染。这样就可以减少第一次打开时用户的等待时间了。(类似与数据分页、图片懒加载的思想,目的是提高首屏性能。)

那么我们可以将一个大的 PDF 文件分成多个小文件,即分片。比如某个 PDF 有 200 页,我们按照 5 页一片,将它切分成 40 片,每次只下载用户看到的那一个分片。然后在用户进行滚动翻页的时候,异步的去下载对应包含对应页的分片。

基本的思路有了,接下来就是想办法实现了。要实现分片加载我们需要做两件事情:

1、服务器对 PDF 文件进行分片

由于这个是服务器做了,所以,交给后端就好了。本文不细讲,大家有兴趣的可以去了解 itextpdf (https://api.itextpdf.com/iText5/java/5.5.11/) 库,它提供了相关 API 对 PDF 进行切片。

我们需要跟后端约定好 PDF 文件分片之后每一片的数据格式。假如分片的大小为 5(即每次请求 5 页内容),那么可以定义数据格式如下:

{  "startPage": 1, // 分片的开始页码  "endPage": 5, // 分片结束页码  "totalPage": 100, // pdf 总页数  "url": "http://test.com/asset/fhdf82372837283.pdf" // 分片内容下载地址}

2、客户端根据用户交互行为获取并渲染指定的分片

显然,获取并渲染是两个操作。为了保证用户操作(滚动)的流畅性,这两个操作我们都异步进行。至此,我们需要解决的关键问题变成两个:

  • 如何下载 PDF 分片
  • 如何渲染 PDF 分片

知识准备 - PDF.js 接口介绍

由于我们无法在已有标签上做修改,所以我们考虑基于 PDF.js 库进行深度定制。那么我们先了解一下 PDF.js 可以为我们提供哪些能力。参考 官方文档(https://mozilla.github.io/pdf.js),下面列举了我们需要用到的几个 API ,由于官方文档中内容比较粗,这里贴上了源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值