HarmonyOS PreviewKit 文件预览功能入门与后端实现
HarmonyOS PreviewKit 提供元服务文件预览能力。通过并发下载文件至沙箱目录,结合 filePreview.openPreview API 实现多文件一次性预览。示例包含客户端 ETS 代码与 Node.js 静态文件后端,涵盖权限配置、网络请求处理及 UI 状态刷新机制,适用于快速搭建下载即预览的工程环境。

HarmonyOS PreviewKit 提供元服务文件预览能力。通过并发下载文件至沙箱目录,结合 filePreview.openPreview API 实现多文件一次性预览。示例包含客户端 ETS 代码与 Node.js 静态文件后端,涵盖权限配置、网络请求处理及 UI 状态刷新机制,适用于快速搭建下载即预览的工程环境。

本文以实际工程为例,快速上手 HarmonyOS 元服务的文件预览能力(PreviewKit),并配套一个后端用于提供示例文件。示例工程路径:
clientserver上图是将 1 个 pdf 文件和 3 个图片一起预览,那么就只会显示第 1 个预览窗口。
下图是移除 pdf 文件,将 3 个同类型的图片放在一起预览
为了方便演示功能,需要先将一些可以预览的文件下载到元服务的沙箱内,是基于这个原因我们才需要引入后端来模拟这个下载的环境,所以元服务内需要先实现下载文件,存储到沙箱,然后再使用预览 API filePreview.openPreview 预览沙箱内的文件。
client/entry/src/main/ets/pages/Index.ets:演示并发下载 4 个文件(1.pdf、1.png、2.png、3.png)并一次性预览。server/index.js 与 server/public/:提供静态文件下载接口 /file/:filename。目标:
HarmonyOS 提供了预览能力包 @kit.PreviewKit。在 ETS 代码中引入:
import { filePreview } from '@kit.PreviewKit';
import { fileUri } from '@kit.CoreFileKit';
核心调用是:
// 先准备多个文件的预览信息
const previewList: 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 类型
};
previewList.push(fileInfo);
}
// 一次性打开多个预览窗口
filePreview.openPreview(uiContext, previewList).then(() => {
// 打开成功
}).catch((err: BusinessError) => {
// 打开失败处理
});
说明:
PreviewInfo 至少需要 title、uri、mimeType。uri 使用 fileUri.getUriFromPath(沙箱文件路径) 构造。PreviewInfo[],实现多文件预览。示例使用 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;
. = ;
. = (..).();
: <>[] = ..( .(p.));
settled = .(promises);
: [] = [];
: [] = (..).();
( i = ; i < settled.; i++) {
name = .[i].;
r = settled[i];
(r. === ) {
successes.(r.);
nextStatuses[i] = ;
} {
nextStatuses[i] = ;
}
}
. = nextStatuses;
. = successes;
. = ;
UI 渲染建议:
ForEach(this.plannedFiles, ...) 动态渲染状态行,避免硬编码索引。@Local 或 @State 修饰,并'重新赋值数组'以触发刷新(不要在原数组上就地修改元素)。Content-Type 推断。data.header['Content-Type'] 索引;示例使用序列化 + 正则方式提取避免 ArkTS 索引限制。// 通过序列化响应头并用正则提取 Content-Type
private tryGetContentTypeHeader(headerObj: Object | null): string {
if (!headerObj) return '';
try {
const json = JSON.stringify(headerObj);
if (!json) return '';
const match = json.match(/"content-type"\s*:\s*"([^"]+)"/i);
return match && match.length > 1 ? match[1] : '';
} catch (_) {
return '';
}
}
保存文件:
const filePath = `${this.filesDir}/${fileName}`;
if (fileIo.accessSync(filePath)) {
fileIo.unlinkSync(filePath);
}
const file = fileIo.openSync(filePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.WRITE_ONLY);
const bytesWritten = fileIo.writeSync(file.fd, fileBuffer);
fileIo.closeSync(file);
权限:
entry/src/main/module.json5 声明 ohos.permission.INTERNET 才能进行网络请求。示例后端路径:d:\code\atoStudy\server,目录 public/ 放置 4 个演示文件。
核心路由:GET /file/:filename
后端的简单目录结构:
// index.js(简版示例)
const express = require('express');
const path = require('path');
const app = express();
app.get('/file/:filename', (req, res) => {
const filename = req.params.filename;
const filePath = path.join(__dirname, 'public', filename);
res.sendFile(filePath); // 或根据需要设置 Content-Type
});
app.listen(3000, () => {
console.log('Server listening on http://localhost:3000');
});
客户端请求地址示例:
private serverBase: string = "http://192.168.5.2:3000/file";
// 组合完整 URL 示例:`${this.serverBase}/1.pdf`
注意:请按真实局域网 IP 替换
192.168.5.2,并保证手机/模拟器与后端在同一网络。
后端:
npm install && node index.jspublic/ 下存在 1.pdf、1.png、2.png、3.png客户端:
module.json5 中确保已声明 ohos.permission.INTERNETohos.permission.INTERNET 是否声明;确认真机/模拟器的网络可达性。/file/:filename 存在且文件确实在 public/ 目录内;检查客户端 serverBase 地址是否正确。Content-Type;如果缺失,则按扩展名推断。this.itemStatuses = [...nextStatuses])。filePreview.openPreview 是 HarmonyOS 文件预览能力的核心,支持一次性打开多文件预览。结合简单的后端静态文件服务与并发下载、响应式状态刷新,能够快速搭建一个'下载即预览'的演示工程。本文的示例工程完整覆盖了从后端文件提供、客户端下载与保存、到预览窗口打开的关键路径,适合作为入门教程与二次扩展的基础。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online