在鸿蒙中如何实现pdf预览功能?

在开发鸿蒙App时,你是否做过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文件下载到沙箱目录代码,可选择使用(不必须)。

四、建议

建议在真机查看预览效果,模拟器展示效果不好,初次加载,第一页总是黑的,有大佬知道怎么解决,请指教~~

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值