哈喽大家好啊. 前半年还挺忙的, 一直也没有发文章, 有老哥想我了嘛. 这两天发现老有人私信问我 PDF 相关的内容.
那么好, 为了我能安心摸鱼, 我准备出一篇文章来介绍一下如何使用 PDFJS.
PDF.JS 是什么?
PDF.JS 由 Mozilla 提供支持. 目标是创建一个通用的, 基于 web 标准的平台, 用于解析和呈现 PDF.
预览 PDF
使用 iframe,embed, 新窗口打开
测试地址, 方案比较简单, 属于看天吃饭, 全靠浏览器爸爸赏.
使用方式
- <embed src="https://www.lilnong.top/static/pdf/B-4-RxJS在React中的应用-龙逸楠_.pdf">
- <iframe src="https://www.lilnong.top/static/pdf/B-4-RxJS在React中的应用-龙逸楠_.pdf">
- </iframe>
测试结果
浏览器 | 兼容性 | 配图 |
---|---|---|
Chrome(PC)(Mac) | 支持 | |
safari(PC)(Mac) | 支持 | |
Firefox(PC)(Mac) | 支持 | |
Firefox(PC)(Windows) | 支持 | |
Edge(PC)(Windows) | 支持 | |
IE(PC)(Windows) | 不支持 | |
微信(Android)(vivo x27) | 不支持 | |
Chrome(Android)(vivo x27) | 不支持 | |
QQ 浏览器(Android)(vivo x27) | 不支持 |
优点: 简单, 支持大部分 PC 浏览器 (IE 不支持). 跨域资源同样可以 (无需 cors)
缺点: 不支持移动端浏览器, 不支持 IE 等低版本浏览器. 样式无法自定义.
pdfjs-view
测试地址, 方案兼容性比较好, 需要资源同域 或者 cors 跨域, 可以自定义样式.
使用方式
自己部署一个 pdfjs-view. (推荐, 更稳定)
下载项目, 然后项目分为两个版本 / Web/viewer-1.html 和
/legacy/Web/viewer.HTML
.legacy 支持低版本浏览器, 使用 es5 编写, 讲道理采用这个方案, 你肯定也是为了兼容所有浏览器.(没有的话, 就 gulp generic-legacy 生成一份)
然后将相关内容复制到你的目录, 上传 FTP.
本质来讲他就是一个 HTML 文件, 所以你可以针对他进行一些修改, 比如说主题颜色, 隐藏下载按钮等等.
使用 CDN 或者官方提供的 pdfjs-view.(不推荐, 不稳定, 异常 CORS)
- https://mozilla.github.io/pdf.js/legacy/web/viewer.html
- https://mozilla.github.io/pdf.js/web/viewer.html
- <iframe src="https://www.lilnong.top/static/project?file=https://www.lilnong.top/static/pdf/B-4-RxJS在React中的应用-龙逸楠_.pdf"></iframe>
- <iframe src="https://www.lilnong.top/static/project/pdfjs-es5-2.5.207/web/viewer-1.html?file=https://www.lilnong.top/static/pdf/B-4-RxJS在React中的应用-龙逸楠_.pdf"></iframe>
测试结果
浏览器 | 兼容性 | 兼容性 ES5 版本 | 配图 |
---|---|---|---|
Chrome(PC)(Mac) | 支持 | 支持 | |
safari(PC)(Mac) | 支持 | 支持 | |
Firefox(PC)(Mac) | 支持 | 支持 | |
Firefox(PC)(Windows) | 支持 | 支持 | |
Edge(PC)(Windows) | 支持 | 支持 | |
IE(PC)(Windows) | 不支持 | 支持 | |
微信(Android)(vivo x27) | 支持 | 支持 | |
Chrome(Android)(vivo x27) | 支持 | 支持 | |
QQ 浏览器(Android)(vivo x27) | 支持 | 支持 |
同上, 可以看到 IE 都支持, 移动端也 OK.
优点: 支持大部分浏览器 (PC,M 端都支持). 跨域资源需要 cors. 样式可以自定义.
缺点: 需要部署一个 view.
pdfjs-canvas
测试地址, 方案比较复杂, 需要自己实现一套预览配套的内容 (分页, 放大缩小).
使用方式
- (function() {
- let el = document.getElementById('canvasWrap');
- if (!el) {
- el = document.createElement('div')
- el.id = 'canvasWrap'
- document.body.appendChild(el)
- }
- el.innerHTML = ''
- let winW = document.documentElement.clientWidth
- // 加载 PDF 资源
- let loadingTask = pdfjsLib.getDocument('https://www.lilnong.top/static/pdf/B-4-RxJS在React中的应用-龙逸楠_.pdf')
- // PDF 加载完成的回调.
- loadingTask.promise.then(function(PDF) {
- console.log('pdf', PDF)
- // 可以获取到总页数.
- let pageNum = PDF.numPages
- var _pageNum = 1;
- var renderPageToCanvas = function(pageNum, auto=false) {
- // 获取其中的一个页面
- PDF.getPage(pageNum).then(function(page) {
- // you can now use *page* here
- _pageNum = pageNum
- // 获取原始大小的数据
- var viewport = page.getViewport({
- scale: 1,
- });
- var scale = (500 / viewport.width).toFixed(2)
- viewport = page.getViewport({
- scale: scale
- });
- var canvas = document.createElement('canvas');
- el.appendChild(canvas)
- var context = canvas.getContext('2d');
- canvas.height = viewport.height;
- canvas.width = viewport.width;
- // 创建了一个 canvas 画板用来存放
- var renderContext = {
- canvasContext: context,
- viewport: viewport
- };
- page.render(renderContext);
- if (auto)
- renderPageToCanvas(pageNum + 1, auto);
- });
- }
- renderPageToCanvas(_pageNum, true);
- canvasPrev.onclick = function() {
- renderPageToCanvas(Math.max(_pageNum - 1, 1));
- }
- canvasNext.onclick = function() {
- renderPageToCanvas(Math.min(_pageNum + 1, PDF.numPages));
- }
- }, function(reason) {
- console.error(reason)
- })
- }
- )()
测试结果
浏览器 | 兼容性 | 配图 |
---|---|---|
Chrome(PC)(Mac) | 支持 | |
safari(PC)(Mac) | 支持 | |
Firefox(PC)(Mac) | 支持 | |
Firefox(PC)(Windows) | 支持 | |
Edge(PC)(Windows) | 支持 | |
IE(PC)(Windows) | 不支持 | |
微信(Android)(vivo x27) | 支持 | |
Chrome(Android)(vivo x27) | 支持 | |
QQ 浏览器(Android)(vivo x27) | 支持 |
兼容性也还可以, 需要依赖 canvas.
下载 PDF
下载头
直接打开
如果浏览器不支持解析 PDF 那么可以触发下载.
如果浏览器支持解析 PDF, 那么会变成预览.
这个时候我们可以给 a 标签加上 download 来触发下载.(需要同域)
总结一下
通过上面的内容我们可以实现前端预览 PDF 功能了, 我们来总结一下各个方案的特征.
方案 | 移动端 | PC 端(高版本浏览器) | PC 端(IE、低版本浏览器) | 跨域 | 复制内容 | 自定义样式(分页、下载等等) |
---|---|---|---|---|---|---|
iframe | ❌(平台不支持) | ✅ | ❌(平台不支持) | ✅ | ✅ | ❌ |
embed | ❌(平台不支持) | ✅ | ❌(平台不支持) | ✅(CORS) | ✅ | ❌ |
pdfjs-view | ✅ | ✅ | ❌(ES6 新特性) | ✅(CORS) | ✅ | ✅(基于原有基础去修改) |
pdfjs-view-es5 | ✅ | ✅ | ✅ | ✅(CORS) | ✅ | ✅(基于原有基础去修改) |
pdfjs-canvas | ✅ | ✅ | ❌(canvas) | ✅(CORS) | ❌(canvas) | ✅(完全需要自己去实现一整套操作) |
好了, 还需要什么内容欢迎留言啊. 我给更新到里面.
来源: https://segmentfault.com/a/1190000040331855