【鸿蒙心迹】HarmonyOS preview 预览文件 Kit 的入门讲解(配套后端代码)

【鸿蒙心迹】HarmonyOS preview 预览文件 Kit 的入门讲解(配套后端代码)

HarmonyOS preview 预览文件 Kit 的入门讲解(配套后端代码)

本文以实际工程为例,快速上手 HarmonyOS 元服务 的文件预览能力(PreviewKit),并配套一个后端用于提供示例文件。示例工程路径:

  • 客户端(HarmonyOS 端):client
  • 后端(Node.js):server


image-20251112091151694

上图是将 1个pdf文件和3个图片一起预览,那么就只会现实第1个预览窗口。

下图是移除pdf文件,将3个同类型的图片放在一起预览

image-20251112091518239

为了方便演示功能,需要先将一些可以预览的文件下载到元服务的沙箱内,是基于这个原因我们才需要引入后端来模拟这个下载的环境,所以元服务内需要先实现下载文件,存储到沙箱,然后再使用预览API filePreview.openPreview预览沙箱内的文件。

1. 工程结构与目标

  • client/entry/src/main/ets/pages/Index.ets:演示并发下载 4 个文件(1.pdf1.png2.png3.png)并一次性预览。
  • server/index.jsserver/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 至少需要 titleurimimeType
  • uri 使用 fileUri.getUriFromPath(沙箱文件路径) 构造。
  • 支持一次性传入一个 PreviewInfo[],实现多文件预览。
图片占位:请补充一次性预览 4 个文件的窗口布局截图,标注窗口标题与 MIME 类型展示位置。

3. 并发下载与状态反馈(客户端)

示例使用 Promise.allSettled 并发下载 4 个后端文件,并按项展示“成功/失败”状态:

// 计划 + 状态@Localprivate plannedFiles: DownloadPlan[]=[];@Localprivate itemStatuses:string[]=[];@Localprivate isDownloading:boolean=false;@Localprivate statusMessage:string='';// 初始化计划(aboutToAppear)this.plannedFiles =[newDownloadPlan('1.pdf',`${this.serverBase}/1.pdf`),newDownloadPlan('1.png',`${this.serverBase}/1.png`),newDownloadPlan('2.png',`${this.serverBase}/2.png`),newDownloadPlan('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 =awaitPromise.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-TypeprivatetryGetContentTypeHeader(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. 后端:简单的静态文件下载接口

示例后端路径:d:\code\atoStudy\server,目录 public/ 放置 4 个演示文件。

核心路由:GET /file/:filename

后端的简单目录结构:

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

近期活动

最近想要想要考取 HarmonyOS 基础或者高级证书,或者快要获取的同学都可以点击这个链接,加入我的班级,考取成功有机会获得鸿蒙礼盒一份。

Read more

最全盘点,赶紧收藏:2025 年全网最全的 Java 技术栈内容梳理(持续更新中)

重阳,2026 年初了(当前 2 月),但 2025 年底到 2026 年初的 Java 技术栈其实变化不算剧烈——主流还是 Spring Boot 3.x + JDK 21/17 LTS + 云原生 的组合,只是虚拟线程、GraalVM 原生镜像、AI 集成、observability 等方向加速落地。 下面给你一份 2025-2026 仍然非常主流且实用的全网最全 Java 技术栈梳理(后端为主,全栈/架构为辅),按 阶段 + 掌握深度 分层,标注了 2025-2026 的真实趋势和“是否强烈推荐”。 0. 基础环境 &

By Ne0inhk
C++之多态

C++之多态

多态 * 什么是多态? * 多态的定义及实现 * 多态的构成条件 * 虚函数 * 虚函数的重写/覆盖 * 关键技术原理 * 最佳实践指南 * 虚函数重写 * 协变 * 析构函数的重写 * override和final关键字 * 纯虚函数和抽象类 * 多态的原理 * 多态是如何实现的 * 1. 虚函数表(vtable) * 虚函数表知识要点 * 2. 虚函数的声明 * 3. 多态的实现过程 * 动态绑定与静态绑定 什么是多态? 多态(Polymorphism)是面向对象编程的三大核心特性之一(封装、继承、多态),源于希腊语"多种形态"。在C++中,它允许我们使用统一的接口处理不同类型的对象,显著提高了代码的灵活性和可扩展性。 核心概念 1. 同一接口,多种形态 不同的对象可以通过相同的方法名调用,但实际执行的逻辑由对象自身的类决定。 2. 解耦调用与实现 调用者只需关注接口(方法名和参数)

By Ne0inhk

iOS设备Minecraft Java版启动器PojavLauncher终极配置与优化指南

iOS设备Minecraft Java版启动器PojavLauncher终极配置与优化指南 【免费下载链接】PojavLauncher_iOSA Minecraft: Java Edition Launcher for Android and iOS based on Boardwalk. This repository contains source code for iOS/iPadOS platform. 项目地址: https://gitcode.com/GitHub_Trending/po/PojavLauncher_iOS 想要在iPhone或iPad上畅玩原汁原味的Minecraft Java版吗?PojavLauncher让这一切成为可能!这款基于Boardwalk项目的开源启动器,专门为iOS设备优化,支持从经典版本到最新快照的所有Minecraft Java版,让你随时随地搭建自己的方块世界。🚀 环境准备与兼容性检测 在开始安装之前,首先需要确认你的设备是否满足运行要求。PojavLauncher对iOS设备有特定的硬件和系统要求,确保设备兼容是成功运行

By Ne0inhk