鸿蒙|能力特性-统一文件预览

0 阅读5分钟

概览:本文从Preview Kit的能力范围、使用约束讲起,逐步演示本地TXT文件预览流程,并重点剖析网络PDF文件的完整处理链路:配置网络权限 → 下载资源至沙箱(≤5MB)→ 构造PreviewInfo → 调用openPreview启动预览。

文件预览概述

Preview Kit(文件预览服务)为应用提供便捷的文件快速预览和文件打开加速能力。应用可以通过Preview Kit提供的预览API,对图片、视频、音频、文本、html进行预览查看,满足绝大多数办公开发的需求,包括:

1、预览展示:呈现文件的基本内容,如文本、图片等,支持选中多文件,在预览列表切换显示。
2、文件分享:将文件以分享的形式传给另一个软件。
3、使用其他软件打开:使用预览打开时,会获取到该文件类型的默认打开软件,然后点击“使用其他应用打开”进行跳转。
4、图片翻转放大:在非2in1设备时,预览能够对图片进行旋转放大等处理。

文件预览约束与限制:

1、支持的国家和地区
➢ 当前Preview Kit仅支持中国境内(不包含中国香港、中国澳门、中国台湾)。
2、支持的设备
➢ 当前Preview Kit支持模拟器开发,但与真机存在部分能力差异。
➢ 模拟器不支持.pdf/.pptx/.xlsx/.docx文件格式预览。

文件预览模式

文件预览所支持的文件类型

类型文件后缀mimeType类型
文本txt、cpp、c、h、java、xhtml、xmltext/plain、text/x-c++src、text/x-csrc、text/x-chdr、text/x-java、application/xhtml+xml、text/xml
网页html、htmtext/html
图片jpg、png、gif、webp、bmp、svgimage/jpeg、image/png、image/gif、image/webp,image/bmp、image/svg+xml
音频m4a、aac、mp3、ogg、wavaudio/mp4a-latm、audio/aac、audio/mpeg、audio/ogg、audio/x-wav
视频mp4、mkv、tsvideo/mp4、video/x-matroska、video/mp2ts
文件夹
文档pdfapplication/pdf起始版本: 5.0.0(12)
Office文档doc、docx、xls、xlsx、ppt、pptx、csv、ofdapplication/msword、application/vnd.openxmlformats-officedocument.wordprocessingml.document、application/vnd.ms-excel、application/vnd.openxmlformats-officedocument.spreadsheetml.sheet、application/vnd.ms-powerpoint、application/vnd.openxmlformats-officedocument.presentationml.presentation、text/csv、general.ofd起始版本: 5.0.0(12)

不同文件预览效果

截屏2026-04-08 15.08.03.png

不同设备类型的预览模式

模态窗:和父窗口绑定,模态窗存在时父窗口不可移动,不可操作,模态窗永远置于父窗口前面。
应用窗:应用窗口,可以通过AMS启动。
AMS:AbilityManagerService,用于协调各Ability运行关系、及对生命周期进行调度的系统服务。

截屏2026-04-08 15.10.36.png

文件预览基本流程实践

文件预览实践注意事项

1、当前Preview Kit仅支持跳出应用进行文件的预览,暂不支持应用内预览。
2、Office类型文档预览借助WPS提供的能力来实现,在预览文档类型文件时会存在”WPS提供技术支持”、”使用WPS Office打开”等相关字样。
3、当前Preview Kit暂不支持安全定制能力,包括禁止截录屏、屏蔽其他应用打开入口、屏蔽分享入口等安全预览能力。
4、当前Preview Kit需要调用方存在对应uri的转授权能力,从而让预览获得该文件的访问权限来正常读取文件。

创建待预览资源、预览目标文件资源

import { common } from '@kit.AbilityKit';
import { fileIo as fs, fileUri } from '@kit.CoreFileKit'
import { filePreview } from '@kit.PreviewKit';

@Entry
@Component
struct Index {
  private context = this.getUIContext().getHostContext() as common.UIAbilityContext;
  private fileName: string = 'preview_info.txt'
  @State uri: string = ''

  build() {
    Column({ space: 10 }) {
      Button('创建待预览资源')
        .onClick(() => {
          // 使用CoreFileKit提供的文件读写能力,在应用沙箱路径中生成及获取待预览文件资源。以txt文本文件预览流程为例。
          let filesDir = this.context.filesDir
          let filePath = filesDir + '/' + this.fileName
          let file: fs.File = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE)
          let uri = fileUri.getUriFromPath(filePath)
          this.uri = uri
          let str: string = 'hello word'
          let writeLen = fs.writeSync(file.fd, str)
          fs.closeSync(file)
        })

      Button('预览目标文件资源')
        .onClick(async () => {
          // 1、使用canPreview判断资源是否可预览。
          let result = await filePreview.canPreview(this.context, this.uri)
          if (result) {
            // 2、构造待预览文件资源的标准数据对象PreviewInfo。
            let previewInfo: filePreview.PreviewInfo = {
              title: this.fileName,
              uri: this.uri,
              mimeType: 'text/plain'
            }
            // 3、使用openPreview完成文件预览。
            filePreview.openPreview(this.context, previewInfo)
          } else {
            this.getUIContext().getPromptAction().showToast({
              message: 'File cannot be previewed'
            })
          }
        })

    }
    .height('100%')
    .width('100%')
  }
}

案例:网络PDF文件预览

网络权限配置及资源限制条件

1、预览服务并不能直接预览在线PDF文件,需要将待预览PDF资源下载至本地沙箱。
2、需配置requestPermissions网络请求权限,否则会导致网络资源下载失败。
3、待预览PDF资源不能大于5M,否则可能报:2300023 向磁盘/应用程序写入接收数据失败。

"requestPermissions": [
  {
    "name": "ohos.permission.INTERNET"
  },
]

封装网络资源下载方法、封装文件预览函数

import { fileIo as fs, fileUri } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';
import { filePreview } from '@kit.PreviewKit';
import { http } from '@kit.NetworkKit';

/**
 * 下载PDF
 * 1、基于http模块封装网络资源下载方法。
 * 2、将下载到的PDF资源,写入本地沙箱路径。
 */
export async function downloadPdf(context: common.UIAbilityContext, url: string, fileName: string): Promise<string> {
  const httpRequest = http.createHttp();
  const filePath = `${context.filesDir}/${fileName}`;
  try {
    const response = await httpRequest.request(url, {
      expectDataType: http.HttpDataType.ARRAY_BUFFER
    });
    if (response.responseCode === 200 && response.result instanceof ArrayBuffer) {
      // 写入文件
      const file = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
      fs.writeSync(file.fd, response.result);
      fs.closeSync(file);
      return filePath;
    } else {
      throw new Error('下载失败');
    }
  } catch (error) {
    console.error('PDF下载出错:', JSON.stringify(error));
    throw new Error('PDF下载出错');
  } finally {
    httpRequest.destroy();
  }
}

/**
 * 预览PDF
 * 1、读取本地沙箱中的PDF资源,注意mimeType需要跟待预览文件保持一致。
 * 2、使用canPreview判断可预览性,使用openPreview实现预览。
 */
export async function previewLocalPdf(context: common.UIAbilityContext, filePath: string) {
  try {
    if (context === undefined) {
      return;
    }
    let file: fs.File = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
    let uri = fileUri.getUriFromPath(filePath);
    fs.closeSync(file);
    let result = await filePreview.canPreview(context, uri);
    if (result) {
      let previewInfo: filePreview.PreviewInfo = {
        title: 'preview',
        uri: uri,
        mimeType: 'application/pdf'
      };
      filePreview.openPreview(context, previewInfo);
    } else {
      console.log('File cannot be previewed.');
    }
  } catch (err) {
    console.error('openPreview error');
  }
}

页面中调用预览方法

import { downloadPdf, previewLocalPdf } from '../utils/previewUtil';
import { common } from '@kit.AbilityKit';
@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  context = this.getUIContext().getHostContext() as common.UIAbilityContext;
  url =
    'https://communityfile-drcn.op.dbankcloud.cn/FileServer/getFile/cmtyPub/011/111/111/0000000000011111111.20250620163901.82504090472134057009843077544703:50001231000000:2800:74101FF0864D8F031151872AA510FA4891B78F9C47AF0398737645DD0CB57250.pdf?needInitFileName=true';
  build() {
    Column({ space: 20 }) {
      Button("预览网络PDF")
        .onClick(async () => {
          let res = await downloadPdf(this.context, this.url, 'harmonyosBook.pdf');
          previewLocalPdf(this.context, res);
        });
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center);
  }
}