【uniapp】App平台展示pdf文件
ios
ios比较简单,可以直接使用如下代码。
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/wiki/Frequently-Asked-Questions#which-browsersenvironments-are-supported
如果需要兼容更低的版本,参考更多版本支持:https://github.com/mozilla/pdf.js/releases
uniapp的web-view组件文档:https://uniapp.dcloud.net.cn/component/web-view.html#app%E7%AB%AFweb-view%E7%9A%84%E6%89%A9%E5%B1%95
新建pdfPreview.vue
直接使用pdfjs提供的viewer.html
参考如下。url为http://xxx.com/xx.pdf。此处需要获取webview并设置style,否则进入页面后,会占用状态栏和导航栏。
<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.titlethis.initWebView();let height = 0; //定义动态的高度变量let statusbar = 0; // 动态状态栏高度uni.getSystemInfo({// 获取当前设备的具体信息success: (sysinfo) => {statusbar = sysinfo.statusBarHeight;height = sysinfo.windowHeight;let currentWebview = this.$scope.$getAppWebview(); //获取当前web-viewsetTimeout(function () {var wv = currentWebview.children()[0];wv.setStyle({//设置web-view距离顶部的距离以及自己的高度,单位为pxtop: 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如下:
<!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行:
// if (fileOrigin !== viewerOrigin) {// throw new Error("file origin does not match viewer's");// }
pdfjs\web\viewer.mjs 22403行:
if (fileOrigin === viewerOrigin || fileOrigin !== viewerOrigin) {return;}
不同的版本可能行号不太一样,搜索file origin看下出现的地方并修改就行。
不使用pdfjs提供的viewer,而是自己写
下面是一个简单的demo:(更多demo可以参考官网)
<!DOCTYPE html><html><head><metaname="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 pendingrenderPage(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 countersdocument.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 renderingrenderPage(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
有了解的大佬请评论区留言
有任何疑问可以共同交流~
