跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
TypeScriptNode.js大前端

HarmonyOS PreviewKit 文件预览功能入门与后端示例

介绍 HarmonyOS 元服务中 PreviewKit 文件预览能力的入门用法。通过构建 Node.js 后端提供静态文件,客户端使用 Promise.allSettled 并发下载 PDF 和图片至沙箱目录,利用 filePreview.openPreview 实现多文件一次性预览。内容涵盖工程结构、核心 API 调用、HTTP 下载细节、权限配置及常见问题排查,适合开发者快速搭建“下载即预览”功能。

微码行者发布于 2026/3/27更新于 2026/10/17100 浏览
HarmonyOS PreviewKit 文件预览功能入门与后端示例

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;

UI 渲染建议:

  • 使用 ForEach(this.plannedFiles, ...) 动态渲染状态行,避免硬编码索引。
  • 将与 UI 绑定的字段用 @Local 或 @State 修饰,并'重新赋值数组'以触发刷新(不要在原数组上就地修改元素)。

4. HTTP 下载的细节与 ArkTS 限制规避

  • MIME 与扩展名:示例通过扩展名推断 MIME,若扩展名缺失则从响应头的 Content-Type 推断。
  • ArkTS 限制:不建议直接 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 才能进行网络请求。

5. 后端:简单的静态文件下载接口

示例后端路径可自定义,目录 public/ 放置 4 个演示文件。

核心路由:GET /file/:filename

后端的简单目录结构:

server/
├── index.js
└── public/
    ├── 1.pdf
    ├── 1.png
    ├── 2.png
    └── 3.png
// 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,并保证手机/模拟器与后端在同一网络。

6. 快速运行与验证

后端:

  • 安装依赖并启动:npm install && node index.js
  • 确认 public/ 下存在 1.pdf、1.png、2.png、3.png

客户端:

  • 在 module.json5 中确保已声明 ohos.permission.INTERNET
  • 构建并安装到设备/模拟器
  • 点击'下载',观察逐项状态变化
  • 下载成功后点击'预览',验证多窗口预览是否正常

7. 常见问题与排查

  • 权限错误(如 code=201 / 'Permission denied'):检查 ohos.permission.INTERNET 是否声明;确认真机/模拟器的网络可达性。
  • 404 或下载失败:确认后端路由 /file/:filename 存在且文件确实在 public/ 目录内;检查客户端 serverBase 地址是否正确。
  • MIME 与扩展名错配:优先使用后端返回的 Content-Type;如果缺失,则按扩展名推断。
  • UI 不刷新:在 ArkUI 中对数组进行'重新赋值'来触发刷新,避免原地修改元素(例如使用 this.itemStatuses = [...nextStatuses])。

8. 小结

filePreview.openPreview 是 HarmonyOS 文件预览能力的核心,支持一次性打开多文件预览。结合简单的后端静态文件服务与并发下载、响应式状态刷新,能够快速搭建一个'下载即预览'的演示工程。本文的示例工程完整覆盖了从后端文件提供、客户端下载与保存、到预览窗口打开的关键路径,适合作为入门教程与二次扩展的基础。

目录

  1. HarmonyOS PreviewKit 文件预览功能入门讲解
  2. 1. 工程结构与目标
  3. 2. PreviewKit 的核心:filePreview.openPreview
  4. 3. 并发下载与状态反馈(客户端)
  5. 4. HTTP 下载的细节与 ArkTS 限制规避
  6. 5. 后端:简单的静态文件下载接口
  7. 6. 快速运行与验证
  8. 7. 常见问题与排查
  9. 8. 小结

更多推荐文章

查看全部
  • AIGC 与虚拟身份及元宇宙的未来:虚拟人物创作与智能交互
  • Cherry Studio 客户端配置与本地大模型远程调用
  • Web 开发者实战:多模态 Agent 图像识别与全栈处理方案
  • OpenClaw 本地部署与 Ollama 集成配置指南
  • PID 循迹机器人控制算法实战:24 电赛 H 题解析
  • 无人机路径规划算法详解:原理与实战应用
  • 一个 SpringBoot + Vue 酒店客房管理系统的实现记录
  • Android Studio 安装与 SDK、JDK、Gradle 配置详解
  • JavaScript 基础语法与 jQuery 入门
  • 如何将 Android 项目上传至 GitHub
  • Visual C++运行库修复指南:解决程序启动失败问题
  • RTX 4090 本地 AI 绘画:Z-Image 写实图像工作流实践
  • AI 代理工具全景:Claude Code 等六大产品深度解析
  • 双指针经典算法题实战解析:从原理到代码
  • C++多态实现深度剖析:从抽象类约束到虚函数表机制
  • Magic API:低代码接口开发平台完全指南
  • N8N Data Table 实现自定义表单数据增删改查实战
  • SAR与ISAR雷达成像核心算法详解
  • Stable Diffusion 3.5 提示词语法校验与错误拦截部署指南
  • Spring MVC 响应处理与设置方法

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online