ios
ios比较简单,可以直接使用如下代码。
js
let url = 'xxx.com/xx.pdf'
uni.downloadFile({
url: url,
success: function (res) {
var filePath = res.tempFilePath;
uni.openDocument({
filePath: filePath,
success: function (res) {
console.log('打开文档成功');
}
});
}
});
安卓
安卓如果没有可以打开的应用,将没有反应。
主流程:使用webview,内嵌pdfjs。
下载pdfjs
下载网址:https://mozilla.github.io/pdf.js/getting_started/#download
注意 :安卓的话建议下载legacy的版本,否则一些api可能有兼容问题.
常见的错误有:Promise.withResolver() is not a function、AbortSignal.any is not a function、invalid regular expression flags等。
如果需要兼容更低的版本,参考更多版本支持:https://github.com/mozilla/pdf.js/releases
uniapp的web-view组件文档:https://uniapp.dcloud.net.cn/component/web-view.html#app端web-view的扩展
新建pdfPreview.vue
直接使用pdfjs提供的viewer.html
参考如下。url为http://xxx.com/xx.pdf。此处需要获取webview并设置style,否则进入页面后,会占用状态栏和导航栏。
js
<template>
<web-view :src="webViewUrl"></web-view>
</template>
<script>
export default {
data() {
return {
pdfUrl: '', // 原始PDF地址
webViewUrl: '', // 本地HTML页面地址
title: '',
};
},
onLoad(options) {
this.pdfUrl = options.url;
this.title = options.title
this.initWebView();
let height = 0; //定义动态的高度变量
let statusbar = 0; // 动态状态栏高度
uni.getSystemInfo({
// 获取当前设备的具体信息
success: (sysinfo) => {
statusbar = sysinfo.statusBarHeight;
height = sysinfo.windowHeight;
let currentWebview = this.$scope.$getAppWebview(); //获取当前web-view
setTimeout(function () {
var wv = currentWebview.children()[0];
wv.setStyle({
//设置web-view距离顶部的距离以及自己的高度,单位为px
top: statusbar + 44, //此处是距离顶部的高度,应该是你页面的头部
height: height - statusbar //webview的高度
});
}, 200); //如页面初始化调用需要写延迟
}
});
},
methods: {
initWebView() {
this.webViewUrl = `/hybrid/html/local.html?title=${this.title}&pdfUrl=${encodeURIComponent(this.pdfUrl)}`;
}
}
};
</script>
<style scoped></style>
hybrid/html
新建local.html如下:
html
<!DOCTYPE html>
<html>
<head>
<meta name="viewport"
content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title>PDF预览</title>
<style>
html {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="url"></div>
<iframe id="iframe" src="" width="100%" height="100vh" style="height: 100vh;width:100vw;border:none;"></iframe>
<script>
document.addEventListener("DOMContentLoaded", function() {
const urlParams = new URLSearchParams(window.location.search);
url = urlParams.get("pdfUrl");
// document.getElementById('url').innerHTML = url;
document.getElementById('iframe').src = 'pdfjs/web/viewer.html?file=' + encodeURIComponent(url)
const title = urlParams.get("title");
if (title) {
document.title = title;
}
});
</script>
</body>
</html>
把下载好的pdfjs解压,放到hybrid/html下,
可以看到这里的src开头为pdfjs/web/viewer.html,也就是pdfjs写好的预览网页。
如果有报错file origin does not match viewer's,可以修改:
pdfjs\web\viewer.js 1614行-1616行:
js
// if (fileOrigin !== viewerOrigin) {
// throw new Error("file origin does not match viewer's");
// }
pdfjs\web\viewer.mjs 22403行:
js
if (fileOrigin === viewerOrigin || fileOrigin !== viewerOrigin) {
return;
}
不同的版本可能行号不太一样,搜索file origin看下出现的地方并修改就行。
不使用pdfjs提供的viewer,而是自己写
下面是一个简单的demo:(更多demo可以参考官网)
html
<!DOCTYPE html>
<html>
<head>
<meta
name="viewport"
content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"
/>
<title>PDF预览</title>
<style>
html {
height: 100%;
width: 100%;
}
.flex {
display: flex;
}
.justify-between {
justify-content: space-between;
}
.gap-10 {
gap: 10px;
}
.items-center {
align-items: center;
}
#the-canvas {
margin-top: 20px;
border: 1px solid grey;
direction: ltr;
}
#loading {
position: absolute;
top: 30%;
left: calc(50% - 15px);
width: 30px;
height: 30px;
border: 2px solid #eee;
border-top-color: #007aff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<div class="flex items-center justify-between">
<div>
<button id="enlarge">放大</button>
<button id="reduce">缩小</button>
</div>
<div class="flex items-center gap-10">
<span
>Page: <span id="page_num"></span> / <span id="page_count"></span
></span>
<button id="prev">上一页</button>
<button id="next">下一页</button>
</div>
</div>
<div id="loading"></div>
<div id="error" style="color:red;"></div>
<div id="canvas-block" style="display: none">
<canvas id="the-canvas"></canvas>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.7.107/pdf.js"></script>
<script>
document.addEventListener("UniAppJSBridgeReady", function () {});
pdfjsLib.GlobalWorkerOptions.workerSrc =
"https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.7.107/pdf.worker.js";
var url = " ",
pdfDoc = null,
pageNum = 1,
pageRendering = false,
pageNumPending = null,
scale = 1,
defaultScale = 1,
isFirstRender = true,
canvas = document.getElementById("the-canvas"),
ctx = canvas.getContext("2d");
// 指定工作线程脚本的路径
function renderPage(num) {
// 加载PDF文档
pdfDoc.getPage(num).then(function (page) {
if (isFirstRender) {
const style = window.getComputedStyle(document.body);
const contentWidth = parseFloat(style.width);
var desiredWidth = contentWidth;
let defaultViewport = page.getViewport({
scale: 1,
});
defaultScale = desiredWidth / defaultViewport.width;
isFirstRender = false;
}
let scaledViewport = page.getViewport({
scale,
});
canvas.width = scaledViewport.width;
canvas.height = scaledViewport.height;
let renderContext = {
canvasContext: ctx,
viewport: scaledViewport,
};
let renderTask = page.render(renderContext);
// 等待渲染完成
renderTask.promise.then(function () {
pageRendering = false;
document.getElementById("loading").style.display = "none";
document.getElementById("canvas-block").style.display = "block";
if (pageNumPending !== null) {
// New page rendering is pending
renderPage(pageNumPending);
pageNumPending = null;
}
}, function (reason) {
document.getElementById("loading").style.display = "none";
document.getElementById("error").innerHTML = document.getElementById("error").innerHTML + '\n Error: renderTask: ' + reason;
});
// Update page counters
document.getElementById("page_num").textContent = num;
}).catch(err => {
document.getElementById("loading").style.display = "none";
document.getElementById("error").innerHTML = document.getElementById("error").innerHTML + '\n Error: getPage: ' + err;
});
}
function queueRenderPage(num) {
if (pageRendering) {
pageNumPending = num;
} else {
renderPage(num);
}
}
function onPrevPage() {
if (pageNum <= 1) {
return;
}
pageNum--;
queueRenderPage(pageNum);
}
document.getElementById("prev").addEventListener("click", onPrevPage);
function onNextPage() {
if (pageNum >= pdfDoc.numPages) {
return;
}
pageNum++;
queueRenderPage(pageNum);
}
document.getElementById("next").addEventListener("click", onNextPage);
function onEnlarge() {
if (pageRendering) {
return;
}
scale += 0.1;
queueRenderPage(pageNum);
}
document.getElementById("enlarge").addEventListener("click", onEnlarge);
function onReduce() {
if (pageRendering) {
return;
}
if (scale <= defaultScale) {
return; // 防止过度缩小
}
scale -= 0.1;
queueRenderPage(pageNum);
}
document.getElementById("reduce").addEventListener("click", onReduce);
document.addEventListener("DOMContentLoaded", function () {
const urlParams = new URLSearchParams(window.location.search);
url = urlParams.get("pdfUrl");
const title = urlParams.get("title");
if (title) {
document.title = title;
}
// document.getElementById('url').textContent = url;
pdfjsLib.getDocument(url).promise.then(function (pdfDoc_) {
pdfDoc = pdfDoc_;
document.getElementById("page_count").textContent = pdfDoc.numPages;
// Initial/first page rendering
renderPage(pageNum);
}).catch(err => {
document.getElementById("loading").style.display = "none";
document.getElementById("error").innerHTML = document.getElementById("error").innerHTML + '\n Error: getDocument: ' + err;
});
});
</script>
</body>
</html>
其它注意事项
- ios 里使用 pdfjs 将无法显示,就算直接打开pdfjs给的demo也无法展示,暂不清楚原因。
https://mozilla.github.io/pdf.js/web/viewer.html
https://mozilla.github.io/pdf.js/legacy/web/viewer.html
有了解的大佬请评论区留言
有任何疑问可以共同交流~