网页在线预览 PDF 的功能怎么做

0 阅读1分钟

合同、对账单丢到后台,点开就要能看。浏览器对 PDF 的支持不齐,微信里更是常常下不下来、打不开。用 PDF.js 自带的 viewer.html 在网页里渲染,翻页和缩放都现成。

入口是 index.html。样式在 css/preview.css,打开窗口的逻辑在 js/preview.js。脚本先引 jQuery,再引 preview.js。真正画页面的是 js/pdf/ 这一套,业务页不要改里面的文件。

在线预览 PDF 用到哪些文件

业务页按这个顺序引:

viewer.html 自己再引 ../build/pdf.js 和 viewer.js。少了 pdf.worker.js,大文件会卡住;少了 cmaps,有的中文 PDF 会缺字。这套目录要整棵带着走,不要只拷两个 js。

维护这一页时入口就是 index.html。PDF 地址写在 preview.js 的 pdfUrl。

页面骨架

.l-btn 用 padding: 8px 16px 撑开,加上 cursor: pointer。

如何打开预览窗口

点 #previewPdf 调 openPdf。里面用 window.open 打开 viewer.html,第二个参数 "PDF" 是窗口名:连点几次会复用同一个窗口,不会弹出一堆标签。

事件挂在 body 上委托。没有地址就 return,不要打开一个空白预览页。弹窗被浏览器拦住时,检查是不是用户手势里触发的;脚本里自动 open 多半会被拦。

要嵌在当前页里看,不要新窗口,把 window.open 换成给 iframe 赋 src,地址拼法和下面一节一样。

PDF 地址如何传给预览页

viewer.html 启动时读地址栏:document.location.search 里有 file 就用它,没有就用库里的 DEFAULT_URL(现在是空字符串)。说白了:业务页只要把文件 URL 接到 ?file= 后面。

地址里常有 &、?、中文文件名,必须 encodeURIComponent 再拼。不编码,查询参数会在第一个 & 处被截断,预览页拿到半截路径,干瞪眼。这坑我见过不止一次。

本地文件写成相对 viewer.html 的路径,例如 ../docs/a.pdf,同样要编码。跨域的 http(s) 地址,服务器要允许 PDF.js 用 XHR 拉文件(CORS 或同域反代)。微信里预览,用 https 地址最稳,http 会被拦。

pdfUrl 集中写在 preview.js 顶部,换文件只改这一处。

预览页如何显示文档

viewer.html 是 PDF.js 的现成界面:左侧缩略图、顶上页码和缩放、中间一页页 canvas。业务页打开它之后,就交给这一页自己跑。

它做三件事:

1、从 ?file= 取出地址,走 webViewerOpenFileViaURL。

2、pdf.js 把文件交给 pdf.worker.js 在 Worker 里解码,主线程不卡。

3、按页画到 #viewer 里,工具栏改页码、缩放、查找、打印都绑在这一套 DOM 上。

语言包走 locale/locale.properties,浏览器语言对得上就会换成中文工具栏。中文内容靠 cmaps/ 里的映射,缺了这目录,有的扫描件还行,有的矢量字会糊成方框。

不要改 viewer.js 里的按钮逻辑。要藏掉下载、打印,用 css 把对应 .toolbarButton 隐藏即可,比改库省事,升级 PDF.js 也不用重做一遍。

如何对接到真实项目中

预览地址换成接口返回的文件 URL。列表点某一条,把 res.data.url 传给 openPdf。jQuery 这套建议用 Layui 做提示,具体按实际项目来定。没有地址、接口失败都走 layer.msg,不要 alert。

/api/file/detail 的路径和字段换成项目里的约定。下面这份覆盖 preview.js,页面结构仍用前面的 html。

按钮或列表项带上 data-id。文件要跟预览页同域,或后台把 PDF 的 CORS 头开好,否则 Worker 拉不到流,页面一直转圈。js/pdf/ 整目录拷到站点里,路径仍相对 index.html 指到 ./js/pdf/web/viewer.html。只要换 URL,预览页本身不用改。