背景
最近自家产品开发使用中收到反馈,安卓内嵌网页无法打开PDF,而IOS可以打开。其实安卓无法打开分以下几种情况:
- 有.pdf后缀但是文档比较小的——可以打开
- 有.pdf后缀但是文档比较大的——无法打开
- 无.pdf后缀的——都打不开
原因分析
Android的内置WebView引擎 主要用于显示网页内容和基本的文本渲染 ,对于复杂的多媒体和特定文件类型的渲染支持有限, 不直接支持打开大型的带有.pdf后缀的PDF文件预览 。 对于不具有.pdf后缀的PDF文件,WebView默认将其视为普通的文本或二进制文件,因此无法直接预览
IOS的WebView使用的是 WebKit引擎 ,该引擎内置了对PDF文件的支持, 可以直接预览和展示PDF内容 。所以IOS的WebView可以打开带有.pdf后缀的文件,并提供内置的PDF查看器,使用户可以直接再应用中查看PDF文件。 对于没有.pdf后缀的文件,IOS仍可以预览并打开,因为IOS系统的预览功能会自动识别文件类型,并使用适当的预览器打开文件 。
这里我主要针对无.pdf后缀的,H5利用Canvas和PDF.js,给一下我开发时的解决方法。不过我也会将我收集到的安卓的方案写这里,不过我不是安卓开发工程师,欢迎补充。
解决方案
安卓方案
- 使用特定的PDF库:Android上有许多为PDF预览和操作提供支持的 第三方库 ,如Adobe PDF Library和MuPDF等。这些库可以在WebView中渲染和打开PDF文件。
- 使用其他应用程序:(通过使用Inteynt机制?),可以调用系统中预装的PDF阅读器应用程序或其他支持PDF的应用程序来打开和预览PDF文件。可以根据文件类型和URI来指定打开PDF文件的应用程序。例如,使用封装pdf的应用程序,如Adobe Acrobat Reader或其他PDF阅读器应用程序
H5使用pdf.js利用Canvas将页面渲染出来
- 引入PDF.js(注意如果要下载下来使用的化, pdf.worker.min.js 也要下载下来)
<script src="https://unpkg.com/pdfjs-dist@1.9.426/build/pdf.min.js"></script>
- 主要JS代码
<script>
// 获取页面参数
// 测试:?pdf=https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf
let url = new URLSearchParams(window.location.search).get("pdf");
let pdfDoc = null;
function createPage() {
let div = document.createElement("canvas");
document.body.appendChild(div);
return div;
}
function renderPage(num) {
pdfDoc.getPage(num).then(function (page) {
let viewport = page.getViewport(2.0);
let canvas = createPage();
let ctx = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
page.render({
canvasContext: ctx,
viewport: viewport
});
});
}
// 如果是由后端的pdf链接地址,且跨域需要携带cookie验证,getDocument中传{ url: url, withCredentials: true }
PDFJS.getDocument({ url: url }).then(function (pdf) {
pdfDoc = pdf;
for (let i = 1; i <= pdfDoc.numPages; i ) {
renderPage(i)
}
})
</script>
附整个页面的代码
代码语言:html复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=4.0, user-scalable=no">
<title>安卓PDF阅读页面</title>
<style>
* {
margin: 0;
padding: 0;
}
canvas {
width: 100%;
height: 100%;
border: 1px solid rgb(221, 221, 221);
}
/* 加载中的转圈圈样式 */
.spinner-box {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 2;
background-color: rgba(0, 0, 0, 0.3);
}
.spinner-box img {
width: 9.3333vw;
height: 9.3333vw;
}
.spinner-box .title {
margin: 2.6667vw 0 0;
font-size: 3.2vw;
color: #fff;
text-shadow: 0px 0px 2px rgba(0, 0, 0, 0.5);
white-space: pre-line;
text-align: center;
}
.spinner-box .spinner {
width: 9.3333vw;
height: 9.3333vw;
animation: rotator 1.4s linear infinite;
}
@keyframes rotator {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(270deg);
}
}
.spinner-box .path {
stroke-dasharray: 187;
stroke-dashoffset: 0;
transform-origin: center;
animation: dash 1.4s ease-in-out infinite, colors 5.6s ease-in-out infinite;
}
@keyframes colors {
0% {
stroke: #fff;
}
25% {
stroke: #f7e7d7;
}
50% {
stroke: #eecfaf;
}
75% {
stroke: #e5b788;
}
100% {
stroke: #dd9f60;
}
}
@keyframes dash {
0% {
stroke-dashoffset: 187;
}
50% {
stroke-dashoffset: 46.75;
transform: rotate(135deg);
}
100% {
stroke-dashoffset: 187;
transform: rotate(450deg);
}
}
</style>
</head>
<script src="https://unpkg.com/pdfjs-dist@1.9.426/build/pdf.min.js"></script>
<body>
<div id="loading" class="spinner-box">
<!-- 上传中 -->
<svg class="spinner" viewBox="0 0 66 66" xmlns="http://www.w3.org/2000/svg">
<circle class="path" fill="none" stroke-width="6" stroke-linecap="round" cx="33" cy="33" r="30"></circle>
</svg>
</div>
<script>
// 获取页面参数
// 测试:?pdf=https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf
let url = new URLSearchParams(window.location.search).get("pdf");
let pdfDoc = null;
function createPage() {
let div = document.createElement("canvas");
document.body.appendChild(div);
return div;
}
function renderPage(num) {
pdfDoc.getPage(num).then(function (page) {
let viewport = page.getViewport(2.0);
let canvas = createPage();
let ctx = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
page.render({
canvasContext: ctx,
viewport: viewport
});
});
}
let loading = document.getElementById("loading")
// 显示加载中
loading.style.display = "flex";
// 如果是由后端的pdf链接地址,且跨域需要携带cookie验证,getDocument中传{ url: url, withCredentials: true }
PDFJS.getDocument({ url: url }).then(function (pdf) {
pdfDoc = pdf;
for (let i = 1; i <= pdfDoc.numPages; i ) {
renderPage(i)
}
// 隐藏加载中
loading.style.display = "none";
})
</script>
</body>
</html>
如有不足,欢迎指正