HarmonyOS 文件预览服务:让你的APP轻松预览各种文件
什么是文件预览服务
你有没有遇到过这种情况:在 App 里下载了一个文件,想看看内容,结果发现打不开?或者需要用别的 App 来打开?文件预览服务(Preview Kit)就是来解决这个问题的。
文件预览服务是鸿蒙生态下的文件预览服务,让你的应用可以直接预览各种文件,不需要跳转到其他 App。它支持 5 种基本类型(txt、html、图片、视频、音频),覆盖 18 种详细文件格式。简单说,就是让你的 App 变成一个"万能文件查看器"。
你可能会问:为什么不直接用系统的文件打开功能?因为系统的文件打开功能需要跳转到别的 App,用户体验不好。而且如果用户没有安装能打开该文件的 App,就更尴尬了。用文件预览服务的话,一切都在你的 App 里完成,用户不用离开你的应用。
核心功能
文件预览服务提供以下功能:
- 文件预览:直接在应用内预览文件,不需要跳转
- 格式支持:支持 txt、html、图片、视频、音频等多种格式
- 预览判断:判断文件是否可以预览,避免用户点了没反应
- 交互体验:支持缩放等交互操作,用户体验好
环境搭建
硬件要求
- 设备类型:华为手机、平板、PC/2in1
- HarmonyOS 系统:HarmonyOS NEXT Developer Beta1 及以上
软件要求
- DevEco Studio 版本:DevEco Studio NEXT Developer Beta1 及以上
- HarmonyOS SDK 版本:HarmonyOS NEXT Developer Beta1 SDK 及以上
搭建步骤
- 安装 DevEco Studio:去华为开发者官网下载安装
- 配置开发环境:确保网络环境正常
- 设备调试:使用真机进行调试
项目结构
└── entry/src/main/ets ├── entryability │ └── EntryAbility.ets // 本地启动 ability └── pages └── Index.ets // 基础预览界面项目结构非常简单,核心逻辑都在Index.ets里。这个 Codelab 的重点就是教你调用预览服务的接口,所以代码量不大。
文件预览流程
下面是文件预览服务的完整使用流程:
支持的文件格式
下面是文件预览服务支持的格式分类:
第一步:导入模块
import{filePreview}from'@kit.PreviewKit';import{promptAction}from'@kit.ArkUI';import{fileIoasfs,fileUri}from'@kit.CoreFileKit';导入的模块有:
filePreview:文件预览服务的核心接口,我们用它来判断文件是否可预览、打开预览。这是整个文章最重要的模块promptAction:弹出提示用的,比如"文件不可预览"这种提示框fs:文件操作,用来创建和写入文件。在这个例子里,我们需要先创建一个测试文件,然后才能预览它fileUri:文件 URI 转换,把文件路径转成 URI 格式。预览服务需要的是 URI 格式的文件路径,不是普通的文件路径
第二步:获取文件路径和 URI
letcontext=getContext(this);letfileDir=context.filesDir;// 获取沙箱路径letfilePath=fileDir+'/'+this.fileName;获取应用的沙箱路径。context.filesDir是应用的私有文件目录,你的文件应该放在这个目录下。
为什么要用沙箱路径?因为鸿蒙系统的安全机制,应用只能访问自己的私有目录。你不能直接访问其他应用的目录或者系统目录。沙箱路径就像你的应用的"私人保险箱",只有你的应用能打开。
letfile=fs.openSync(filePath,fs.OpenMode.READ_WRITE|fs.OpenMode.CREATE);leturi=fileUri.getUriFromPath(filePath);打开文件并获取 URI:
fs.openSync打开文件,如果不存在就创建。READ_WRITE表示可读可写,CREATE表示如果文件不存在就创建一个新的fileUri.getUriFromPath把文件路径转成 URI 格式(file://docs/...)。预览服务需要的是 URI 格式,不是普通的文件路径。这个转换是必须的,不转的话预览服务不认识
第三步:写入文件内容
letstr:string="hello, world";letwriteLen=fs.writeSync(file.fd,str);console.info("write data to file succeed and size is:"+writeLen);fs.closeSync(file);写入一些测试内容到文件里:
fs.writeSync写入字符串内容。file.fd是文件描述符,可以理解为"文件的代号"fs.closeSync关闭文件。关闭之后就不能再读写了,所以一定要在写完之后再关闭
这一步是为了演示,实际使用时你的文件可能已经存在了,不需要写入。比如用户下载了一个 PDF 文件,你想预览它,直接用它的 URI 就行了。
第四步:判断文件是否可预览
letresult=awaitfilePreview.canPreview(context,uri);调用filePreview.canPreview判断文件是否可以预览。传入上下文和文件 URI,返回true或false。
这个步骤很重要,因为不是所有文件格式都支持预览。先判断一下,如果不支持预览,可以给用户一个友好的提示,比如"该文件类型不支持预览"。如果不判断就直接调用预览,可能会报错或者显示空白。
第五步:打开预览
if(result){letpreviewInfo:filePreview.PreviewInfo={title:this.fileName,uri:uri,mimeType:'text/plain'};filePreview.openPreview(getContext(this),previewInfo);}else{promptAction.showToast({message:'文件不可预览'});}如果文件可以预览,就创建PreviewInfo对象并调用filePreview.openPreview打开预览。
PreviewInfo包含三个字段:
title:预览页面的标题,会显示在预览界面的顶部。一般用文件名就行uri:文件的 URI,就是前面转换出来的那个mimeType:文件的 MIME 类型,告诉预览服务这个文件是什么类型的
常见的 MIME 类型:
text/plain:纯文本文件(.txt)text/html:HTML 文件(.html、.htm)image/png:PNG 图片image/jpeg:JPEG 图片(.jpg、.jpeg)video/mp4:MP4 视频audio/mpeg:MP3 音频
MIME 类型一定要设置对,否则预览服务可能不知道怎么处理这个文件。比如你把一个图片文件的 MIME 类型设成了text/plain,预览服务就会把它当文本文件来处理,显示出来的就是一堆乱码。
如果文件不可预览,弹出一个 Toast 提示用户。这样用户就知道为什么点了没反应,而不是以为 App 卡了。
完整代码
把上面的步骤合在一起,完整的代码是这样的:
import{filePreview}from'@kit.PreviewKit';import{promptAction}from'@kit.ArkUI';import{fileIoasfs,fileUri}from'@kit.CoreFileKit';@Entry@Componentstruct Index{privatefileName:string='preview_info.txt';build(){Row(){Column(){Button('openPreview').onClick(async()=>{letcontext=getContext(this);letfileDir=context.filesDir;letfilePath=fileDir+'/'+this.fileName;letfile=fs.openSync(filePath,fs.OpenMode.READ_WRITE|fs.OpenMode.CREATE);leturi=fileUri.getUriFromPath(filePath);letstr:string="hello, world";letwriteLen=fs.writeSync(file.fd,str);console.info("write data to file succeed and size is:"+writeLen);fs.closeSync(file);letresult=awaitfilePreview.canPreview(context,uri);if(result){letpreviewInfo:filePreview.PreviewInfo={title:this.fileName,uri:uri,mimeType:'text/plain'};filePreview.openPreview(getContext(this),previewInfo);}else{promptAction.showToast({message:'文件不可预览'});}})}.width('100%')}.height('100%')}}整个流程就是:点击按钮 → 创建文件 → 获取 URI → 判断是否可预览 → 打开预览。
看起来代码挺长的,但其实大部分都是在做准备工作(创建文件、获取 URI)。真正和预览服务相关的就两行:canPreview和openPreview。
实际应用场景
文件预览服务在实际开发中有很多用途:
文件管理器
// 文件管理器中预览文件asyncfunctionpreviewFile(filePath:string,mimeType:string){letcontext=getContext(this);leturi=fileUri.getUriFromPath(filePath);letcanPreview=awaitfilePreview.canPreview(context,uri);if(canPreview){letpreviewInfo:filePreview.PreviewInfo={title:filePath.split('/').pop()||'',uri:uri,mimeType:mimeType};filePreview.openPreview(context,previewInfo);}else{promptAction.showToast({message:'该文件类型不支持预览'});}}在文件管理器里,用户点击文件时,先判断是否支持预览,支持的话直接打开预览页面。filePath.split('/').pop()是从文件路径里提取文件名,比如从/data/files/document.pdf提取出document.pdf。
下载管理器
// 下载完成后预览文件asyncfunctiononDownloadComplete(filePath:string,fileName:string){letcontext=getContext(this);leturi=fileUri.getUriFromPath(filePath);letcanPreview=awaitfilePreview.canPreview(context,uri);if(canPreview){letpreviewInfo:filePreview.PreviewInfo={title:fileName,uri:uri,mimeType:getMimeType(fileName)};filePreview.openPreview(context,previewInfo);}}functiongetMimeType(fileName:string):string{letext=fileName.split('.').pop()?.toLowerCase()||'';letmimeMap:Record<string,string>={'txt':'text/plain','html':'text/html','htm':'text/html','png':'image/png','jpg':'image/jpeg','jpeg':'image/jpeg','gif':'image/gif','mp4':'video/mp4','mp3':'audio/mpeg'};returnmimeMap[ext]||'application/octet-stream';}在下载管理器里,文件下载完成后,可以直接调用预览服务让用户查看文件内容。getMimeType函数根据文件扩展名自动判断 MIME 类型,这样你就不需要手动指定了。
application/octet-stream是默认的 MIME 类型,表示"二进制文件"。如果文件扩展名不在映射表里,就用这个默认值。预览服务可能会根据文件内容自动判断类型。
聊天应用
// 聊天应用中预览收到的文件asyncfunctionpreviewReceivedFile(fileUri:string,fileName:string){letcontext=getContext(this);letcanPreview=awaitfilePreview.canPreview(context,fileUri);if(canPreview){letpreviewInfo:filePreview.PreviewInfo={title:fileName,uri:fileUri,mimeType:getMimeTypeFromName(fileName)};filePreview.openPreview(context,previewInfo);}else{promptAction.showToast({message:'请下载后查看'});}}在聊天应用里,收到文件时,可以直接预览,不需要先下载到本地。这样用户可以快速查看文件内容,决定是否需要下载。
适用场景
文件预览服务适合以下场景:
- 文件管理器:文件内容预览
- 下载管理器:下载文件预览
- 聊天应用:聊天文件预览
- 办公应用:文档预览
- 媒体应用:图片、视频、音频预览
注意事项
- 文件格式:不是所有文件格式都支持预览,要先调用
canPreview判断 - MIME 类型:要正确设置文件的 MIME 类型,否则可能无法正确预览
- 文件路径:文件要在应用的沙箱目录下,或者有访问权限
- 大文件:预览大文件时可能会有加载时间,要做好用户体验,比如加个 loading 提示
- 错误处理:预览可能会失败(文件损坏、格式不支持等),要做好错误处理
总结
文件预览服务让你的应用轻松预览各种文件,核心流程:
- 导入文件预览服务模块
- 获取文件路径和 URI
- 调用
canPreview判断文件是否可预览 - 创建
PreviewInfo对象,设置标题、URI、MIME 类型 - 调用
openPreview打开预览
掌握了这些,你就能让你的应用支持各种文件的预览功能,提升用户体验。
