下面介绍 2 种在线预览 PDF 的方法,不过都需要 HTML5 的支持,应该问题不大
- 转换 PDF 为 HTML
- 使用 HTML5 的 Canvas 在线绘制 PDF
转换 PDF 为 HTML
pdf2htmlEX 是一个开源的库,能将 PDF 转换成 HTML,支持 Mac,Linux,Windows,其 github 地址为 https://github.com/coolwanglu/pdf2htmlEX。
安装:
- Mac: brew install pdf2htmlEX
- Linux 和 Windows 请参考 https://github.com/coolwanglu/pdf2htmlEX/wiki/Building
使用:
图片,CSS,JS 等都嵌入到 HTML 中:
1
pdf2htmlEX test.pdf
图片,CSS,JS 等都被提取出来保存为文件:
1
pdf2htmlEX --embed cfijo --dest-dir out test.pdf
更多使用说明请参考 https://github.com/coolwanglu/pdf2htmlEX/wiki/Quick-Start
优点:
- 开源
- 转换效果真的很完美
- 微信等移动端都支持
缺点:
- 浏览器必须支持 HTML5
- 转换出来的文件很大,例如 3M 的 PDF 转换出来大概有 30M
Pdf.js 显示 PDF
pdf.js 是一个主要用于 HTML5 平台上在线阅读 PDF 文档的小插件,基于 JS 技术编写而成,无需任何本地技术支持,由 Mozilla Labs 发布的,他们的目标是创建一个通用的,基于标准的网络平台,能够解析和渲染 PDF 文件,并最终发布一个 PDF 阅读器扩展。
下面就用最简单的代码来演示 pdf.js 的使用,显示 PDF 的第一页:
1 |
|
下面的代码一次性显示 PDF 的所有页:
1 |
|
提示: 先创建每一页的 canvas 进行占位,但不显示这一页的内容,当滚动到某一页可见的时候才绘制 PDF 的这一页,加快显示的效率。
上面的例子需要 pdf.js 和 pdf.worker.js 这 2 个文件,去哪里找呢?
打开 https://github.com/mozilla/pdf.js ,根据说明自己编译,或者点击 releases 进行下载。
优点:
- 开源
- 微信等移动端都支持
- 和转换 PDF 为 HTML 的方式比较起来,需要的流量小很多
缺点:
- 浏览器必须支持 HTML5
- 使用 Canvas 绘制的 PDF 不能够选择文字,文字不够清晰
Pdf.js 的 PDFViewer
为了解决上面 pdf.js 简单在 Canvas 中绘制的 PDF 不够清晰,使用 Webpack 管理的项目中如 Vue-Cli 创建的项目可以使用 pdf.js web 案例中提供的 PDFViewer
来进行显示 PDF,有以下优点:
- 根据 PDF 的内容自动决定使用 Canvas 还是文本进行显示
- 能够选择文本
- 懒加载,有加载动画
- 显示 PDF 的所有页
可以参考源码的 examples/components
下的例子,或者按照下面的步骤进行:
添加依赖:
yarn add pdfjs-dist
复制
node_modules/pdfjs-dist/build/pdf.worker.min.js
到项目的静态资源文件夹下,如public/static/lib/pdf.worker.min.js
为了使得 PDF 能够跟随
pdf-viewer-container
自动调整大小,可以使用 CSS-Element-Queries,下载得到 ResizeSensor.js,复制到项目的静态资源文件夹下,如public/static/lib/ResizeSensor.js
,并在 index.html 中引入<script src="/static/lib/ResizeSensor.js"></script>
,如果不需要这个功能,删除下面代码的 35 行处new ResizeSensor
即可使用下面的代码就可以显示 PDF 了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75<template>
<div ref="container" class="pdf-viewer-container">
<div ref="viewer" class="pdfViewer"></div>
</div>
</template>
<script>
import 'pdfjs-dist/web/pdf_viewer.css';
import pdfjsLib from 'pdfjs-dist';
import { PDFViewer } from 'pdfjs-dist/web/pdf_viewer';
// 提示: 如果没有设置 workerSrc,大多数 PDF 都能正常显示,但是某些 PDF 中文字显示不出来
// 需要把 pdf.worker.min.js 放到项目的静态文件目录下
pdfjsLib.GlobalWorkerOptions.workerSrc = '/static/lib/pdf.worker.min.js';
export default {
data() {
return {
url: '/static/foo.pdf',
pdf: null,
};
},
mounted() {
const pdfContainer = this.$refs.container;
const pdfViewer = new PDFViewer({
container: pdfContainer,
viewer: this.$refs.viewer,
});
// PDF 的宽度为 container 的宽度
pdfContainer.addEventListener('pagesinit', () => {
pdfViewer.currentScaleValue = 'page-width'; // Change pdfViewer's default scale.
});
// eslint-disable-next-line
new ResizeSensor(pdfContainer, () => {
pdfViewer.currentScaleValue = 'page-width';
});
// Loading PDF document
pdfjsLib.getDocument({ url: this.url, cMapPacked: true }).then(pdf => {
this.pdf = pdf;
pdfViewer.setDocument(pdf);
});
},
computed: {
pageCount() {
return this.pdf ? this.pdf.numPages : '0';
}
}
};
</script>
<style lang="scss">
.pdf-viewer-container {
.pdfViewer {
.page {
border: none; // 去掉边框
border-image: none;
margin-bottom: 40px;
// 显示页码
// 每个 .page 上都有页码的属性 data-page-number="3", CSS 中可以通过 attr 读取这个属性
&::after {
position: relative;
display: block;
width: 100%;
height: 40px;
line-height: 40px;
text-align: center;
content: '第 ' attr(data-page-number) ' 页';
}
}
}
}
</style>data.url
为 PDF 的路径,修改为自己项目里 PDF 的具体路径把上面的 Vue 模板修改为组件,在 props 中定义 url,通过参数传入进来就可以重复使用了
为了让 PDF 的缩放更舒服一些,还可以使用 Underscore.js 的
_.debounce()
函数进行优化在非 Webpack 的项目中,也就是一个普通的页面里,我们也提取出了相关的文件写了个简单的例子,下载 pdf-reader.7z 照做即可 (需要放在 Web 服务中运行)
在线预览 PDF 的其他方式
在线预览 PDF 还有很多种其他方法,可以参考 http://www.open-open.com/news/view/1fc3e18/
思考
需要在线显示 PPT,也是想到要把 PPT 转换为 HTML 然后在线预览,但是找了好久都没有找到一个免费、并且好用的软件来进行转换,但是把 PPT 转换为 PDF 的免费软件却不少,那么是不是可以考虑先把 PPT 转换为 PDF,然后在通过上面的方法在线预览 PDF 呢?