移动端h5预览PDF文件

利用pdf.js实现h5预览pdf的功能

背景

在iOS上,直接打开PDF的url便可以直接预览,但是在安卓上,WebView不支持PDF解析,因此会通过连接Google的一个服务器转换成功后返回给WebView显示,也就是会跳转到另一个url去(http://docs.google.com/gview?embedded=true&url=PDF_URL)
那么被墙了或者是这个pdf是私密需鉴权的话,就完全不可用了,因此需要借助第三方库来实现这个功能。

实现

pdf.js拥有29.4k的star数,是一个不错的选择,以react项目为例,先安装相关依赖:
npm install pdfjs-dist --save
如果有用到typescript的话还需要安装
npm install @types/pdfjs-dist --save-dev

接着就可以开发相关页面了

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
import React, { useEffect } from 'react';
import './index.less'
// pdfjs-dist/webpack which is the zero-configuration method for Webpack users:
import pdfjs from 'pdfjs-dist/webpack';

// 创建canvas
function createPage() {
const div = document.createElement("canvas");
const container = document.getElementById('pdf-container')
container && container.appendChild(div);
return div;
}

// canvas渲染
function renderPage(pdfDoc: any, num: any) {
pdfDoc.getPage(num).then(function (page: any) {
var viewport = page.getViewport({scale:2.0});
var canvas = createPage();
var ctx = canvas.getContext('2d');

canvas.height = viewport.height;
canvas.width = viewport.width;

page.render({
canvasContext: ctx,
viewport: viewport
});
});
}


const PDFViewer = (props: any) => {
// 可以通过props传入url
const { pdf_url } = props

useEffect(() => {
if (pdf_url) {
window.bridge.showFullLoading()
pdfjs.getDocument(pdf_url).promise
.then(function (pdf) {
for (let i = 1; i <= pdf.numPages; i++) {
renderPage(pdf,i)
}
})
.finally(() => {
window.bridge.hideFullLoading()
})
}
}, [pdf_url])

return (
<div id="pdf-container"/>
)
}

export default PDFViewer

// index.css
/*
#pdf-container canvas {
width: 100%;
height: 100%;
}
*/

getDocument还能自定义Header,withCredentials等参数,便于通过权限校验

效果

image.png