HarmonyOS PreviewKit 文件预览功能入门讲解
本文以实际工程为例,快速上手 HarmonyOS 元服务 的文件预览能力(PreviewKit),并配套一个后端用于提供示例文件。示例工程路径:
- 客户端(HarmonyOS 端):
client - 后端(Node.js):
server
为了方便演示功能,需要先将一些可以预览的文件下载到元服务的沙箱内。基于此原因我们引入后端来模拟下载环境,元服务内需要先实现下载文件、存储到沙箱,然后再使用预览 API filePreview.openPreview 预览沙箱内的文件。
1. 工程结构与目标
client/entry/src/main/ets/pages/Index.ets:演示并发下载 4 个文件(1.pdf、1.png、2.png、3.png)并一次性预览。server/index.js与server/public/:提供静态文件下载接口/file/:filename。
目标:
- 点击'下载'按钮,并发下载上述 4 个文件到应用沙箱目录。
- 下载成功后点击'预览',一次性打开最多 4 个文件的预览窗口。
2. PreviewKit 的核心:filePreview.openPreview
HarmonyOS 提供了预览能力包 @kit.PreviewKit。在 ETS 代码中引入:
import { filePreview } from '@kit.PreviewKit';
import { fileUri } from '@kit.CoreFileKit';
核心调用是:
// 先准备多个文件的预览信息
const prewList: filePreview.PreviewInfo[] = []
for (let i = 0; i < count; i++) {
const item = this.lastDownloadedList[i];
const fileInfo: filePreview.PreviewInfo = {
title: item.name, // 预览标题
uri: fileUri.getUriFromPath(item.path), // 将沙箱路径转成 Uri
mimeType: item.mime || 'application/octet-stream', // MIME 类型
};
prewList.push(fileInfo);
}
// 一次性打开多个预览窗口
filePreview.openPreview(uiContext, prewList).then(() => {
// 打开成功
}).catch((err: BusinessError) => {
// 打开失败处理
});
说明:
PreviewInfo至少需要title、uri、mimeType。uri使用fileUri.getUriFromPath(沙箱文件路径)构造。- 支持一次性传入一个
PreviewInfo[],实现多文件预览。
3. 并发下载与状态反馈(客户端)
示例使用 Promise.allSettled 并发下载 4 个后端文件,并按项展示'成功/失败'状态:
// 计划 + 状态
@Local private plannedFiles: DownloadPlan[] = [];
@Local private itemStatuses: string[] = [];
@Local private isDownloading: boolean = false;
@Local private statusMessage: string = '';
// 初始化计划(aboutToAppear)
this.plannedFiles = [
new DownloadPlan('1.pdf', `${this.serverBase}/1.pdf`),
new DownloadPlan('1.png', `${this.serverBase}/1.png`),
new DownloadPlan('2.png', `${this.serverBase}/2.png`),
new DownloadPlan('3.png', `${this.serverBase}/3.png`)
];
this.itemStatuses = ['未下载', '未下载', '未下载', '未下载'];
// 点击'下载'
this.isDownloading = true;
this.statusMessage = '下载中...';
this.itemStatuses = newArray(this.plannedFiles.length).fill('下载中...');
const promises: Promise<DownloadInfo>[] = this.plannedFiles.map(p => this.downloadFile(p.url));
const settled = await Promise.allSettled(promises);
// 汇总结果并一次性触发 UI 刷新
const successes: DownloadInfo[] = [];
const nextStatuses: string[] = newArray(this.plannedFiles.length).fill('未下载');
for (let i = 0; i < settled.length; i++) {
const name = this.plannedFiles[i].name;
const r = settled[i];
if (r.status === 'fulfilled') {
successes.push(r.value);
nextStatuses[i] = `✓ 下载成功:${name}`;
} else {
nextStatuses[i] = `✗ 下载失败:${name}(${this.errorToString(r.reason as Object)})`;
}
}
this.itemStatuses = nextStatuses; // 重新赋值以触发 UI 刷新
this.lastDownloadedList = successes;
this.isDownloading = false;


