在开发鸿蒙App时,你是否做过pdf预览功能,是否也和我一样碰壁了,那么来看看我是如何解决的吧,废话少说,直接上代码。
在鸿蒙中如何实现pdf预览功能?
一、预览本地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(); // 实例化Base64Helper
let num = fs.readSync(file.fd, buf); // 读取文件
let data = base64.encodeSync(new Uint8Array(buf.slice(0, num))) // 转换成Uint8Array
let textDecoder = util.TextDecoder.create('utf-8', { ignoreBOM: true })
let retStr = textDecoder.decodeWithStream(data, { stream: false }); // 可以把Uint8Array转码成base64
let fileName = file.name
fs.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 Record<string, string>).url || '';
this.getTempFile((router.getParams() as Record<string, string>).url as string);
}
}
这里附有将pdf文件下载到沙箱目录代码,可选择使用(不必须)。
四、建议
建议在真机查看预览效果,模拟器展示效果不好,初次加载,第一页总是黑的,有大佬知道怎么解决,请指教~~
标签:web,预览,鸿蒙,文件,let,pdf,webview From: https://blog.csdn.net/twk857857/article/details/141192492