流光年华|VUE 实现高性能的 PDF 在线预览

最近在实现共享 PDF 文档的需求 , 存在主讲人这样一个角色 , 上传 PDF 文档后 , 通知其它连接中的终端 , 进行实时同步展示的功能 。 对于这样的需求 , pdf.js 成功的让我想起了它 。
PDF 文档的预览 , 总的就是要加载速度快 , 尽最快的速度完成渲染 , 呈现给用户看 , 不要出现长时间的白屏或 Loading 状态的现象 , 另外 PDF 文档需要支持翻页等操作 。 具体看看一步步的实现 。
流光年华|VUE 实现高性能的 PDF 在线预览文档分片下载速度
PDF 文档上传分片上传文档 , 支持秒传 , VUE 支持分片上传的插件一搜一大把 , 可以采用 vue-simple-uploader 等 , 具体如何实现 , 这里不详细论述 , 简单贴一下秒传校验的实现 。
import SparkMD5 from 'spark-md5';/** * 文件秒传 MD5 校验 * @param file 上传的文件信息 */md5File(file) {const fileReader = new FileReader(),blobSlice = File.prototype.slice,chunkSize = 1024 * 1000,// 分片大小chunks = Math.floor(file.size / chunkSize),// 总的分片数量spark = new SparkMD5.ArrayBuffer();// 三方库 SparkMD5let currentChunk = 0;// 加载分片const loadNext = () => {const start = currentChunk * chunkSize;let end = file.size;if (currentChunk < chunks - 1) end = start + chunkSize;fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end));}// 暂停文件上传file.pause();// 开始校验文件MD5loadNext();fileReader.onload = (e) => {spark.append(e.target.result);// 小于总分片, 继续加载if (currentChunk < chunks - 1) {currentChunk++;loadNext();} else {// 分片全部加载完成, 生成 MD5const md5 = spark.end();// 开始服务端校验 MD5 ( 秒传 )this.md5Success(md5, file);}};fileReader.onerror = () => {// 文件读取出错, 取消上传console.log(`文件${file.name}读取出错 , 请检查该文件`);file.cancel();};}
流光年华|VUE 实现高性能的 PDF 在线预览文件秒传MD5校验
PDF 文档分片一个 PDF 文档 , 无法一次就预览所有内容 , 在有限的可视区域内 , 只能显示有限的内容 , 那我们就获取能在有限区域内所能展示的那部分内容 , 以加快 Content Download 的速度 , 减少用户第一次打开时的 Loading 时间 。
假设一个 PDF 文档有 1000 页 , 以 5 页为一片 , 将该文档切分成 200 个分片 , 首次打开默认请求第一个分片 , 其后根据翻页来确定是否继续加载后续的分片信息(如需刷新后仍然展示刚刚所在页 , 则需记录当前页 , 根据该值与分片的页数来确定当前属于第几个分片 , 进而再请求相应分片即可) 。
服务端如何进行分片 , 则交给服务端就好了 , 这里就不详细说了(得注意下中文乱码的情况) 。 假设文件信息格式及单个分片的请求地址如下所示:
/** * 文件信息. * 在文件上传后即可拿到. */const file = {id: 1,md5: 'e10adc3949ba59abbe56e057f20f883e',total: 1000,name: 'VUE 如何实现高性能的 PDF 在线预览',// ...}/** * 请求分片. * $http 是我针对 axios 的一些常用方法 , 拦截器等重新封装后工具类库 */
流光年华|VUE 实现高性能的 PDF 在线预览文件信息格式及分片请求地址格式
请求 PDF 分片pdf.js 接口中 , getDocument 可用于获取远程文档 , 返回 PDFDocumentLoadingTask 对象 , 该对象是一个下载远程 PDF 文档的任务 , 提供了一些监听方法 , 可通过 promise 拿到下载完成的 PDF 对象 , 最终会生成并返回 PDFDocumentProxy 对象 , 我们接下来所有的操作都是基于该代理类进行的 。


推荐阅读