wordpress采集翻译,seo难不难,网站有图片的验证码是怎么做的,百度网址ip鸿蒙ArkTs如何实现pdf预览功能#xff1f; 前言PDFKit运行示例代码报错真机运行先看效果一、预览本地pdf文件二、预览线上的pdf文件三、预览沙箱目录中pdf的文件(重点)效果中的整体代码总结 Harmony OS NEXT版本#xff08;接口及解决方案兼容API12版本或以上版本) 前言
在开… 鸿蒙ArkTs如何实现pdf预览功能 前言PDFKit运行示例代码报错真机运行先看效果一、预览本地pdf文件二、预览线上的pdf文件三、预览沙箱目录中pdf的文件(重点)效果中的整体代码总结 Harmony OS NEXT版本接口及解决方案兼容API12版本或以上版本) 前言
在开发鸿蒙App时你是否做过pdf预览功能。是否也和我一样碰壁了来看看我遇到的问题以及我是如何实现的吧。
PDFKit运行示例代码报错
the requested module hms:officeservice.PdfView does not provide an export name pdfViewManager which imported by xxxx
真机运行
本来以为用真机就能运行了没想到还是报错 那么下面来看看我是如何实现的吧
先看效果 视频转完gif视觉上看起来有点卡实际运行不卡。
一、预览本地pdf文件
预览本地的pdf文件很简单使用Web组件加载即可。 pdf文件目录harmonyApp\entry\src\main\resources\rawfile\test.pdf 具体代码如下
import web_webview from ohos.web.webview;Entry
Component
struct Index {webviewController: web_webview.WebviewController new web_webview.WebviewController();build() {Column() {// src-本地pdf文件Web({ src: $rawfile(test.pdf), controller: this.webviewController }).layoutWeight(1).domStorageAccess(true)}.height(100%)}
}
二、预览线上的pdf文件
这里的线上的pdf文件是指可以在浏览器直接打开预览的pdf文件还有一种是在浏览器打开是直接进入下载的那么就需要我们进一步处理了第三点有详解。 这样的文件预览也很简单使用Web组件加载即可。 具体代码如下
import web_webview from ohos.web.webview;Entry
Component
struct Index {webviewController: web_webview.WebviewController new web_webview.WebviewController();build() {Column() {// 线上pdf链接Web({ src: http://www.cztouch.com/upfiles/soft/testpdf.pdf, controller: this.webviewController }).layoutWeight(1).domStorageAccess(true)}.height(100%)}
}
三、预览沙箱目录中pdf的文件(重点)
这种就比较麻烦了有的pdf链接在浏览器打开直接跳转下载不会预览那么就需要我们下载到沙箱目录中再预览沙箱目录中的pdf文件。 我这里用到了一个pdfviewer工具可从我的百度网盘免费获取 拿到文件夹后放在以下目录 项目目录harmonyApp\entry\src\main\resources\rawfile 具体实现代码如下
import router from ohos.router;
import web_webview from ohos.web.webview;
import { BusinessError, request } from kit.BasicServicesKit;
import showToast from ../../common/utils/ToastUtils;
import { common } from kit.AbilityKit;
import fs from ohos.file.fs;
import { util } from kit.ArkTS;interface IBase64 {base64: string;fileName: string;
}Entry
Component
struct Index2 {controller: web_webview.WebviewController new web_webview.WebviewController()// pdf文件路径State fileUrl: string // 本地沙箱文件地址State tempFilePath: string // 是否显示按钮State isShowBtn: boolean true;build() {Stack() {Column() {// 页面内容Scroll(){Column(){if(this.tempFilePath){if(this.isShowBtn){Button(打开文件).onClick((){this.isShowBtn false;})}else{Web({ src: $rawfile(pdfviewer/viewer.html), controller: this.controller }).onProgressChange((event){console.log(newProgress, event?.newProgress)}).domStorageAccess(true) // 设置是否开启文档对象模型存储接口DOM Storage API权限默认未开启。.onPageEnd((){let file this.sandBoxPdfToBase64(this.tempFilePath);this.controller.runJavaScript(openFile(${file.base64}, ${file.fileName}));})}}}.width(100%).height(100%)}.edgeEffect(EdgeEffect.Fade).width(100%).layoutWeight(1).align(Alignment.TopStart)}.height(100%).backgroundColor(Color.White)}}// 沙箱pdf文件转base64方法sandBoxPdfToBase64(url: string) {let file fs.openSync(url, fs.OpenMode.READ_WRITE); // 打开文件let stat fs.statSync(url); // 获取文件状态let buf new ArrayBuffer(stat.size); // 创建一个ArrayBuffer对象let base64 new util.Base64Helper(); // 实例化Base64Helperlet num fs.readSync(file.fd, buf); // 读取文件let data base64.encodeSync(new Uint8Array(buf.slice(0, num))) // 转换成Uint8Arraylet textDecoder util.TextDecoder.create(utf-8, { ignoreBOM: true })let retStr textDecoder.decodeWithStream(data, { stream: false }); // 可以把Uint8Array转码成base64let fileName file.namefs.closeSync(file);return { base64: retStr, fileName: fileName } as IBase64;}// 下载pdf文件获取沙箱文件目录getTempFile(fileUrl:string){let context getContext(this) as common.UIAbilityContext;const fileFullName fileUrl.split(/)[fileUrl.split(/).length - 1]let tempFilePath ${context.filesDir}/${fileFullName};//文件如果已经存在就删除if (fs.accessSync(tempFilePath)) {fs.unlink(tempFilePath)}request.downloadFile(getContext(), { url: fileUrl,filePath: tempFilePath }).then((data: request.DownloadTask) {let downloadTask: request.DownloadTask data;let progressCallback (receivedSize: number, totalSize: number) {// 这里可以自行编写下载进度条showToast(下载大小${receivedSize},总大小${totalSize});};let completeCallback (){showToast(下载完毕);this.tempFilePath tempFilePath;}downloadTask.on(progress, progressCallback);downloadTask.on(complete, completeCallback)}).catch((err: BusinessError) {console.error(Failed to request the download. Code: ${err.code}, message: ${err.message});})}// 组件生命周期:组件即将出现时回调该接口aboutToAppear() {console.log(进入页面)// 你的pdf链接this.fileUrl (router.getParams() as Recordstring, string).url || ;this.getTempFile((router.getParams() as Recordstring, string).url as string);}
}
这里附有将pdf文件下载到沙箱目录代码可选择使用(不必须)。
效果中的整体代码
import web_webview from ohos.web.webview;
import promptAction from ohos.promptAction
import { BusinessError, request } from kit.BasicServicesKit;
import { common } from kit.AbilityKit;
import fs from ohos.file.fs;
import { util } from kit.ArkTS;// pdf页面tab接口
interface pageTab {name:string;
}interface IBase64 {base64: string;fileName: string;
}/*** pdfPage的ViewModel*/
class PdfPageModel {// 当前索引curTabIndex:number 0;// pdf页面tabtabList:pageTab[] [{ name:预览本地PDF文件 },{ name:预览网络PDF文件 },{ name:预览沙箱PDF文件 },];// 网络文件fileUrl: string http://www.cztouch.com/upfiles/soft/testpdf.pdf// 本地沙箱文件地址tempFilePath: string constructor() {}// 沙箱pdf文件转base64方法sandBoxPdfToBase64(url: string) {let file fs.openSync(url, fs.OpenMode.READ_WRITE); // 打开文件let stat fs.statSync(url); // 获取文件状态let buf new ArrayBuffer(stat.size); // 创建一个ArrayBuffer对象let base64 new util.Base64Helper(); // 实例化Base64Helperlet num fs.readSync(file.fd, buf); // 读取文件let data base64.encodeSync(new Uint8Array(buf.slice(0, num))) // 转换成Uint8Arraylet textDecoder util.TextDecoder.create(utf-8, { ignoreBOM: true })let retStr textDecoder.decodeWithStream(data, { stream: false }); // 可以把Uint8Array转码成base64let fileName file.namefs.closeSync(file);return { base64: retStr, fileName: fileName } as IBase64;}// 下载pdf文件获取沙箱文件目录getTempFile(fileUrl:string){let context getContext(this) as common.UIAbilityContext;const fileFullName fileUrl.split(/)[fileUrl.split(/).length - 1]let tempFilePath ${context.filesDir}/${fileFullName};//文件如果已经存在就删除if (fs.accessSync(tempFilePath)) {fs.unlink(tempFilePath)}request.downloadFile(getContext(), { url: fileUrl,filePath: tempFilePath }).then((data: request.DownloadTask) {let downloadTask: request.DownloadTask data;let progressCallback (receivedSize: number, totalSize: number) {// 这里可以自行编写下载进度条// showToast(下载大小${receivedSize},总大小${totalSize});};let completeCallback (){// showToast(下载完毕);this.tempFilePath tempFilePath;}downloadTask.on(progress, progressCallback);downloadTask.on(complete, completeCallback)}).catch((err: BusinessError) {console.error(Failed to request the download. Code: ${err.code}, message: ${err.message});})}// tab切换switchTab(index:number){this.curTabIndex index;if(index 2 !this.tempFilePath){try {promptAction.showDialog({title: 温馨提示,message: 有些pdf线上链接是经过第三方加密过的在浏览器访问时不能直接预览直接走的是下载的pdf文件链接可以采用这种方式先下载在沙箱目录中然后再预览沙箱中的pdf文件,buttons: [{text: 知道了,color: #000000}]}, (err, data) {if (err) {console.error(showDialog err: err);return;}console.info(showDialog success callback, click button: data.index);});} catch (error) {console.error(Failed to show dialog. Code: ${error.code}, message: ${error.message});}this.getTempFile(this.fileUrl);}}
}Entry
Component
struct PdfPage {webviewController: web_webview.WebviewController new web_webview.WebviewController();State vm: PdfPageModel new PdfPageModel();// 验证是否选中VerifySelectedFun( curIndex:number , itemIndex:number ):boolean{return curIndex itemIndex}aboutToAppear(): void {try {promptAction.showDialog({title: 温馨提示,message: 在模拟器中运行首次加载会出现黑屏但来回切换几次tab标签就好了有条件的建议使用真机运行不会有这样的问题,buttons: [{text: 知道了,color: #000000}]}, (err, data) {if (err) {console.error(showDialog err: err);return;}console.info(showDialog success callback, click button: data.index);});} catch (error) {console.error(Failed to show dialog. Code: ${error.code}, message: ${error.message});}}build() {Stack() {Column() {// tab标签条Row(){Scroll(){Row(){ForEach(this.vm.tabList,(item:pageTab,index){Row(){if(this.VerifySelectedFun(this.vm.curTabIndex,index)){Stack(){Row(){}.width(40).height(10).borderRadius(20).offset({y:7}).linearGradient({angle:89.11,colors:[[rgba(255, 255, 255, 0.55),0.0682],[rgba(217, 217, 217, 0),1]]})Text(item.name).fontSize(18).fontColor($r(app.color.primary_theme_color)).fontWeight(600).height(100%)}}else{Text(item.name).fontSize(16)// .fontColor($r(app.color.font_color_default)).fontWeight(400)}}.height(100%).justifyContent(FlexAlign.Start).padding({ left: index 0 ? 0 : 20 }).onClick((){this.vm.switchTab(index)})})}}.edgeEffect(EdgeEffect.Fade).layoutWeight(1).align(Alignment.Center).scrollable(ScrollDirection.Horizontal).scrollBar(BarState.Off)}.width(100%).height(50).justifyContent(FlexAlign.Start).padding({left:16,right:16}).backgroundColor(Color.White)// 页面内容Scroll(){Column(){if(this.vm.curTabIndex 0 ){// web组件加载本地pdf文件Web({ src: $rawfile(Git.pdf), controller: this.webviewController}).domStorageAccess(true).onProgressChange((event){console.log(newProgress, event?.newProgress)})}else if(this.vm.curTabIndex 1){// web组件加载网络pdf文件Web({ src: http://www.cztouch.com/upfiles/soft/testpdf.pdf, controller: this.webviewController }).layoutWeight(1).domStorageAccess(true).onProgressChange((event){console.log(newProgress, event?.newProgress)})}else if(this.vm.curTabIndex 2){if(this.vm.tempFilePath){Web({ src: $rawfile(pdfviewer/viewer.html), controller: this.webviewController }).onProgressChange((event){console.log(newProgress, event?.newProgress)}).domStorageAccess(true) // 设置是否开启文档对象模型存储接口DOM Storage API权限默认未开启。.onPageEnd((){let file this.vm.sandBoxPdfToBase64(this.vm.tempFilePath);this.webviewController.runJavaScript(openFile(${file.base64}, ${file.fileName}));})}}}.padding({ left: 16, right: 16, bottom: 16 })}.edgeEffect(EdgeEffect.Fade).width(100%).layoutWeight(1).align(Alignment.TopStart)}.height(100%).backgroundColor(#F5F5F5).padding({ bottom: 16 })}}
}
总结
总体来说就是使用Web组件加载pdf文件在模拟器中运行首次运行会黑屏不过来回切换一下tab页就好了真机运行没有问题。 为啥要存到沙箱中再预览岂不是多此一举 当然不是因为有的pdf文件是通过第三方加密过的在浏览器打开链接时是不能直接预览的而是直接走下载了。这时就需要先存到沙箱目录中再预览。
有需要的朋友拿走不谢求赞求赞求赞~ 关注我不迷路不定时分享鸿蒙难点亮点
Harmony OS NEXT版本接口及解决方案兼容API12版本或以上版本)