找回密码
 立即注册
首页 业界区 业界 HarmonyOS运动开发:深度解析文件预览的正确姿势 ...

HarmonyOS运动开发:深度解析文件预览的正确姿势

端木茵茵 前天 08:24
鸿蒙核心技术##运动开发##Core File Kit(文件基础服务)##Preview Kit(文件预览服务)#

1.jpeg

在 HarmonyOS 开发中,文件预览功能是一个常见的需求,尤其是在处理用户上传的图片、文档、音频或视频等资源时。然而,实现文件预览并非一帆风顺,尤其是在涉及文件权限和预览窗口管理时。本文将以“选择好的文件进行预览”为主题,深入解析 HarmonyOS 中文件预览的核心要点,并分享一些实际开发中的经验技巧,帮助开发者避免常见的坑。
前言:文件预览的痛点与挑战
在 HarmonyOS 中,文件预览功能看似简单,实则暗藏诸多细节。开发者常常会遇到诸如文件权限不足、预览窗口无法正常打开或重复打开等问题。这些问题不仅影响用户体验,还可能导致应用崩溃或数据丢失。因此,掌握正确的文件预览实现方式至关重要。
核心要点:文件 URI 权限持久化
在 HarmonyOS 中,通过DocumentViewPicker拿到的文件 URI 仅具有临时权限,这种权限无法直接用于文件预览,否则会导致预览失败。因此,我们需要对文件 URI 进行持久化权限处理。
权限持久化代码解析
  1. await fileShare.persistPermission([
  2.   {
  3.     uri: uri,
  4.     operationMode: fileShare.OperationMode.READ_MODE
  5.   }
  6. ]);
复制代码
• fileShare.persistPermission:这是关键的持久化方法,它将文件 URI 的权限从临时变为持久,确保预览功能能够正常访问文件。
• uri:这是文件的路径,需要确保其格式正确。
• operationMode:这里指定为READ_MODE,表示仅授予读取权限,这是预览功能所需要的最低权限。
此外,为了使用persistPermission方法,还需要在应用的config.json文件中声明以下权限:
  1. {
  2.   "name": "ohos.permission.FILE_ACCESS_PERSIST"
  3. }
复制代码
获取文件 MIME 类型
在预览文件之前,我们需要明确文件的 MIME 类型,这对于预览功能的正确性至关重要。以下是获取 MIME 类型的代码实现:
  1. private getMimeType(filePath: string): string {
  2.   const extension = filePath.split('.').pop()?.toLowerCase() || '';
  3.   switch (extension) {
  4.     case 'jpg':
  5.     case 'jpeg':
  6.       return 'image/jpeg';
  7.     case 'png':
  8.       return 'image/png';
  9.     case 'gif':
  10.       return 'image/gif';
  11.     case 'bmp':
  12.       return 'image/bmp';
  13.     case 'webp':
  14.       return 'image/webp';
  15.     case 'mp4':
  16.       return 'video/mp4';
  17.     case 'mov':
  18.       return 'video/quicktime';
  19.     case 'avi':
  20.       return 'video/x-msvideo';
  21.     case 'mp3':
  22.       return 'audio/mpeg';
  23.     case 'wav':
  24.       return 'audio/wav';
  25.     case 'ogg':
  26.       return 'audio/ogg';
  27.     case 'txt':
  28.     case 'log':
  29.       return 'text/plain';
  30.     case 'html':
  31.     case 'htm':
  32.       return 'text/html';
  33.     default:
  34.       return 'application/octet-stream';
  35.   }
  36. }
复制代码
代码解析
• filePath.split('.').pop():通过文件路径获取文件扩展名,这是判断 MIME 类型的关键。
• switch语句:根据扩展名返回对应的 MIME 类型。这里涵盖了常见的图片、视频、音频、文本和 HTML 文件类型。
• 默认值:如果文件类型无法识别,则返回application/octet-stream,这是一种通用的二进制流类型。
预览文件的实现细节
预览文件的实现涉及多个步骤,包括检查文件是否存在、是否可预览、准备预览参数以及管理预览窗口。以下是完整的代码实现:
  1. async previewFile(): Promise<void> {
  2.   if (!this.selectedFilePath) {
  3.     promptAction.showToast({ message: '请先选择文件', duration: 2000 });
  4.     return;
  5.   }
  6.   try {
  7.     let uiContext = this.getUIContext().getHostContext() as Context;
  8.     // 1. 检查文件是否存在
  9.     try {
  10.       await fs.access(this.selectedFilePath);
  11.     } catch {
  12.       promptAction.showToast({ message: '文件不存在或不可访问', duration: 2000 });
  13.       return;
  14.     }
  15.     // 2. 检查是否可预览
  16.     const uri = this.selectedFilePath.startsWith('file://') ?
  17.       this.selectedFilePath :
  18.       `file://${this.selectedFilePath}`;
  19.     await fileShare.persistPermission([
  20.       {
  21.         uri: uri,
  22.         operationMode: fileShare.OperationMode.READ_MODE
  23.       }
  24.     ]);
  25.     const canPreview = await filePreview.canPreview(uiContext, uri);
  26.     if (!canPreview) {
  27.       promptAction.showToast({ message: '不支持预览此文件类型', duration: 2000 });
  28.       return;
  29.     }
  30.     // 3. 准备预览参数
  31.     const fileInfo: filePreview.PreviewInfo = {
  32.       title: this.fileName,
  33.       uri: uri,
  34.       mimeType: this.getMimeType(this.selectedFilePath)
  35.     };
  36.     // 4. 检查是否已有预览窗口
  37.     const hasDisplayed = await filePreview.hasDisplayed(uiContext);
  38.     if (hasDisplayed) {
  39.         // 已有窗口则关闭
  40.         await filePreview.closePreview(uiContext)
  41.     } else {
  42.       // 新开预览窗口
  43.       const displayInfo: filePreview.DisplayInfo = {
  44.         x: 100,  // 窗口起始x坐标
  45.         y: 100,  // 窗口起始y坐标
  46.         width: 800, // 窗口宽度
  47.         height: 800 // 窗口高度
  48.       };
  49.       await filePreview.openPreview(uiContext, fileInfo, displayInfo);
  50.     }
  51.     console.info('文件预览成功');
  52.   } catch (err) {
  53.     const error = err as BusinessError;
  54.     console.error(`预览失败,错误码: ${error.code}, 错误信息: ${error.message}`);
  55.     promptAction.showToast({
  56.       message: `预览失败: ${error.message}`,
  57.       duration: 2000
  58.     });
  59.   }
  60. }
复制代码
代码解析
• 检查文件是否存在:通过fs.access方法检查文件路径是否有效。
• 持久化文件权限:使用fileShare.persistPermission方法确保文件 URI 具有持久化读取权限。
• 检查是否可预览:调用filePreview.canPreview方法判断文件类型是否支持预览。
• 准备预览参数:构建filePreview.PreviewInfo对象,包含文件标题、URI 和 MIME 类型。
• 管理预览窗口:通过filePreview.hasDisplayed检查是否已有预览窗口。如果存在,则调用filePreview.closePreview关闭窗口;如果不存在,则调用filePreview.openPreview新开预览窗口。
总结:文件预览的正确实现之道
在 HarmonyOS 开发中,实现文件预览功能需要关注文件权限、MIME 类型获取以及预览窗口管理等多个方面。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册