在使用uniapp开发移动端时,微信开发者工具里webview能正常打开后端接口返回的pdf文件流。正式发布后,在配置了业务域名和服务器域名的前提下,预览pdf文件却只能看到白屏,因此我猜测微信小程序不能通过webview读取文件流。这个想法有问题的话请大家给与指正。
后来我通过uniapp api将文件下载在临时目录,再调用api打开,实现了微信小程序的预览。但在安卓端会调用安装的WPS打开,如果用户没有安装pdf阅读器,则无法打开,造成了不好的用户体验。因此,手机端我用pdf.js实现在线预览。
苹果IOS直接使用webview预览pdf。
h5我刚开始的时候使用webview无法预览。报错: no enabled plugin supports this MIME type。所以h5也使用pdf.js实现在线预览,但是我遇到cors跨域问题。后来采用blob实现了在线预览。
后端的api接口如下:
/** * @功能:pdf预览 */ @IgnoreAuth @RequestMapping("/pdf/preview/**") public void pdfPreviewIframe(HttpServletRequest request, HttpServletResponse response) { String imgPath = extractPathFromPattern(request); // 其余处理略 InputStream inputStream = null; OutputStream outputStream = null; try { inputStream = MinioUtil.getMinioFile(imgPath); outputStream = response.getOutputStream(); response.setContentType("application/pdf; charset=UTF-8"); byte[] buf = new byte[1024]; int len; while ((len = inputStream.read(buf)) > 0) { outputStream.write(buf, 0, len); } response.flushBuffer(); } catch (Exception e) { log.error("预览文件失败" + e.getMessage()); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { log.error(e.getMessage(), e); } } if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { log.info("imgPath:{}", imgPath); log.error(e.getMessage(), e); } } } }
一、下载pdf.js
http://mozilla.github.io/pdf.js/getting_started
二、解压文件并引入到项目
说明:网上很多案例说,在项目目录下创建hybrid文件夹,把解压后的文件全部放到里面的方式我试了后行不通。
查阅了官方文档,发现是我肤浅了。
必须严格按照上面说是的目录才行。
在static目录下新建pdfview目录,将解压后的文件拷贝到该目录下。如下图所示:
注释viewer.mjs代码,pdf.js不支持加载跨域文件,会报 “file origin does not match viewer’”错误:
三、 webview内预览pdf
<template> <view> <web-view :src="fileUrl"></web-view> </view></template><script> export default { data() { return { fileUrl: "", pdfViewUrl: '/static/pdfview/web/viewer.html' } }, onLoad(options) { this.fileUrl = decodeURI(options.fileUrl) if (!!options.isPdfView) { this.fileUrl = this.pdfViewUrl + '?file=' + encodeURI(this.fileUrl) } }, methods: { } }</script><style></style>
四、安卓、微信小程序分别预览
//h5预览pdf h5PdfView(item) { uni.showLoading({ title: '加载中...' }) uni.request({ url: this.baseFileURL + '/pdf/preview/' + item.resourceId, method: 'POST', responseType: 'arraybuffer' }).then(res => { uni.hideLoading() let pdfData = res.data let blob = new Blob([pdfData], { type: 'application/pdf;charset=UTF-8' }) pdfData = window.URL.createObjectURL(blob) this.h5PdfUrl = encodeURIComponent(pdfData) uni.navigateTo({ url: '/subpages/webview/webview?fileUrl=' + this.h5PdfUrl + "&isPdfView=true", }) }) }, //pdf预览 pdfView(item) { item.fileUrl = this.baseFileURL + '/pdf/preview/' + item.resourceId // #ifdef APP-PLUS switch (uni.getSystemInfoSync().platform) { case "android": console.log("android") uni.navigateTo({ url: '/subpages/webview/webview?fileUrl=' + encodeURI(item.fileUrl) + "&isPdfView=true", }) break; case "ios": console.log("ios") uni.navigateTo({ url: '/subpages/webview/webview?fileUrl=' + encodeURI(item.fileUrl), }) break; } // #endif // #ifdef H5 this.h5PdfView(item) // #endif // #ifdef MP-WEIXIN let fileName = item.resourceId.substring(item.resourceId.lastIndexOf('/') + 1); uni.downloadFile({ url: item.fileUrl, //文件地址 filePath: wx.env.USER_DATA_PATH + '/' + fileName, success: function(res) { const filePath = res.filePath || res.tempFilePath; uni.openDocument({ filePath: filePath, showMenu: false, success: function(res) {} }); } }); // #endif }
五:预览效果