uni-app 开发鸿蒙应用---uts实现媒体文件下载并保存到体系相册 ...

农民  金牌会员 | 2025-3-17 06:37:55 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 976|帖子 976|积分 2928

uni-app 开发鸿蒙应用---uts实现媒体文件下载并保存到体系相册 

当前编译器版本:HBuilderX 4.26 Alpha版
 当前工程文件:template-1.3.7.tgz
uni-app 开发鸿蒙应用 | uni-app官网 (dcloud.net.cn)
目的:媒体文件下载并保存到体系相册;
实现方法:通过uts插件方式接入鸿蒙原生api,实现媒体文件下载并保存到体系相册。
难点:uts插件暂时只允许api情势导入,无法使用保存控件,且鸿蒙 'ohos.permission.WRITE_IMAGEVIDEO' 权限申请较难考核通过,决定使用保存图片api:showAssetsCreationDialog 实现。
https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-photoaccesshelper-V5#showassetscreationdialog12
一、新建uts插件;

按照官网步骤新建uts插件
UTS插件介绍 | uni-app-x (dcloud.net.cn)
uni-app 开发鸿蒙应用 | uni-app官网 (dcloud.net.cn)
1. 右键 uni_modules 目录新建 uni_modules 插件,定名为 ha-downloadToSystemAlbum


2. 修改插件根目录的 package.json 中的 uni_modules 节点,新增如下配置


  1. {
  2.         ...其他属性
  3.         "uni_modules": {
  4.                 "uni-ext-api": {
  5.                         "uni": {
  6.                                 "openAppProduct": {
  7.                                         "name": "hmDownloadToSystemAlbum",
  8.                                         "app": {
  9.                                                 "js": false,
  10.                                                 "kotlin": false,
  11.                                                 "swift": false,
  12.                                                 "arkts": true
  13.                                         }
  14.                                 }
  15.                         }
  16.                 },
  17.                 ...其他属性
  18.         }
  19. }
复制代码
 3. 编写插件根目录下的 /utssdk/interface.uts 文件,内容如下

  1. /**
  2. * interface.uts
  3. * uts插件接口定义文件,按规范定义接口文件可以在HBuilderX中更好的做到语法提示
  4. */
  5. /**
  6. * myApi 异步函数的参数,在type里定义函数需要的参数以及api成功、失败的相关回调函数。
  7. */
  8. export type MyApiOptions = {
  9.         fullUrl : string,
  10.         renameUrl : string,
  11.         fileType : string,
  12.         success ?: (res : MyApiResult) => void,
  13.         fail ?: (res : string) => void,
  14.         progress ?: (res : any) => void,
  15. }
  16. /**
  17. * 函数返回结果
  18. * 可以是void, 基本数据类型,自定义type, 或者其他类型。
  19. * [可选实现]
  20. */
  21. export type MyApiResult = {
  22.         fieldA : number,
  23.         fieldB : boolean,
  24.         fieldC : string
  25. }
  26. /**
  27. * 函数返回结果
  28. * 可以是void, 基本数据类型,自定义type, 或者其他类型。
  29. * [可选实现]
  30. */
  31. export type MyApiFail = {
  32.         errMessage : string
  33. }
  34. /* 异步函数定义 */
  35. export type MyApi = (options : MyApiOptions) => void
  36. /* 同步函数定义 */
  37. export type MyApiSync = (fullUrl : string) => MyApiResult
复制代码
4. 编写插件根目录下的 /utssdk/app-harmony/index.uts 文件(没有则新建),内容如下 

  1. /* 引入 interface.uts 文件中定义的变量 */
  2. import { MyApiOptions, MyApi } from '../interface.uts';
  3. import request from '@ohos.request'; // 下载
  4. import { fileUri } from '@kit.CoreFileKit'; // 获取getUriFromPath
  5. import { photoAccessHelper } from '@kit.MediaLibraryKit'; // 保存到相册
  6. import fs, { ReadOptions, WriteOptions } from '@ohos.file.fs';
  7. import dataSharePredicates from '@ohos.data.dataSharePredicates';
  8. // 1.是否同意下载-->同意:获取需要保存到媒体库的位于应用沙箱的媒体uri
  9. // 2.文件下载-->progress:98%
  10. // 3.已下载的沙箱文件写入已获取的媒体uri文件中-->progress:100%
  11. export const hmDownloadToSystemAlbum : MyApi = async function (options : MyApiOptions) {
  12.         let context : Context = getContext();
  13.         let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context);
  14.         let filesDir = context.filesDir;
  15.         let cfg : request.DownloadConfig = {
  16.                 url: options.fullUrl,
  17.                 filePath: filesDir + '/' + options.renameUrl,
  18.                 enableMetered: true
  19.         }
  20.         let downloadTask : request.DownloadTask;
  21.         // 1.是否同意下载-->同意:获取需要保存到媒体库的位于应用沙箱的图片/视频uri
  22.         try {
  23.                 let srcFileUri : string = fileUri.getUriFromPath(cfg.filePath) || '';
  24.                 let srcFileUris : Array<string> = [srcFileUri];
  25.                 let fileType : photoAccessHelper.PhotoType = photoAccessHelper.PhotoType.IMAGE;
  26.                 if (options.fileType === 'photo') fileType = photoAccessHelper.PhotoType.IMAGE;
  27.                 if (options.fileType === 'video') fileType = photoAccessHelper.PhotoType.VIDEO;
  28.                 let photoCreationConfigs : Array<photoAccessHelper.PhotoCreationConfig> = [
  29.                         {
  30.                                 title: options.renameUrl.split('.')[0] || '', // 可选-图片或者视频的标题,例如'test2'
  31.                                 fileNameExtension: options.renameUrl.split('.').pop() || '', // 必填-文件扩展名,例如'jpg'
  32.                                 photoType: fileType, // 必填-创建的文件类型,IMAGE或者VIDEO
  33.                                 subtype: photoAccessHelper.PhotoSubtype.DEFAULT, // 可选-图片或者视频的文件子类型,DEFAULT[默认照片类型]或者MOVING_PHOTO[动态照片文件类型]
  34.                         }
  35.                 ];
  36.                 let desFileUris : Array<string> = await phAccessHelper.showAssetsCreationDialog(srcFileUris, photoCreationConfigs);
  37.                 let URI = desFileUris[0];
  38.                 // 2.文件下载98%
  39.                 if (desFileUris.length > 0) {
  40.                         let progressNum : number = 0;
  41.                         options?.progress?.(progressNum);
  42.                         try {
  43.                                 request.downloadFile(context.getApplicationContext(), cfg
  44.                                         , (err, data) => {
  45.                                                 if (err) {
  46.                                                         console.error('Failed to request the download. Cause: ' + JSON.stringify(err));
  47.                                                         return;
  48.                                                 }
  49.                                                 downloadTask = data;
  50.                                                 // 进度条
  51.                                                 let progressCallback = (receivedSize : number, totalSize : number) => {
  52.                                                         // console.info("download receivedSize:" + receivedSize + " totalSize:" + totalSize);
  53.                                                         let numA : number = Math.round((totalSize / 98));
  54.                                                         let numB : number = Math.round((receivedSize / numA));
  55.                                                         options?.progress?.(numB);
  56.                                                 };
  57.                                                 downloadTask.on('progress', progressCallback);
  58.                                                 // 下载完成
  59.                                                 downloadTask.on("complete", async () => {
  60.                                                         // console.log('下载完成', JSON.stringify(options));
  61.                                                         try {
  62.                                                                 // 判定文件是否存在
  63.                                                                 if (fs.accessSync(URI)) {
  64.                                                                         // 删除文件
  65.                                                                         fs.unlinkSync(URI)
  66.                                                                 }
  67.                                                                 let srcFile = fs.openSync(cfg.filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
  68.                                                                 let destFile = fs.openSync(URI, fs.OpenMode.READ_WRITE);
  69.                                                                 // 读取源文件内容并写入至目的文件
  70.                                                                 let bufSize = 4096;
  71.                                                                 let readSize = 0;
  72.                                                                 let buf = new ArrayBuffer(bufSize);
  73.                                                                 let readOptions : ReadOptions = {
  74.                                                                         offset: readSize,
  75.                                                                         length: bufSize
  76.                                                                 };
  77.                                                                 let readLen = fs.readSync(srcFile.fd, buf, readOptions);
  78.                                                                 while (readLen > 0) {
  79.                                                                         readSize += readLen;
  80.                                                                         let writeOptions : WriteOptions = {
  81.                                                                                 length: readLen
  82.                                                                         };
  83.                                                                         fs.writeSync(destFile.fd, buf, writeOptions);
  84.                                                                         readOptions.offset = readSize;
  85.                                                                         readLen = fs.readSync(srcFile.fd, buf, readOptions);
  86.                                                                 }
  87.                                                                 // 关闭文件
  88.                                                                 fs.closeSync(srcFile);
  89.                                                                 fs.closeSync(destFile);
  90.                                                                 return options?.progress?.(100);
  91.                                                         } catch (e) {
  92.                                                                 //TODO handle the exception
  93.                                                                 options?.fail?.('下载失败,请重试');
  94.                                                         }
  95.                                                 })
  96.                                         });
  97.                         } catch (err) {
  98.                                 options?.fail?.('下载失败,请重试');
  99.                                 console.error('err.code : ' + err.code + ', err.message : ' + err.message);
  100.                         }
  101.                 } else {
  102.                         // 取消授权
  103.                         options?.fail?.('已取消');
  104.                 }
  105.         } catch (err) {
  106.                 console.error('showAssetsCreationDialog failed, errCode is ' + err.code + ', errMsg is ' + err.message);
  107.         }
  108. }
复制代码

二、接入鸿蒙原生api,实现授权、下载、保存功能;

完备代码如上 /utssdk/app-harmony/index.uts 文件
1. 调用 showAssetsCreationDialog 接口拉起保存确认弹窗,获取已创建并授予保存权限的uri列表;

2. 若同意授权,调用 request.downloadFile 下载媒体文件到沙箱路径;

3. 在下载完成回调中,将下载的沙箱文件源内容写入至目的已授权uri中。


三、在页面中使用

1. import 引入

  1.         // #ifdef APP-HARMONY
  2.         // 仅鸿蒙会编译
  3.         import {
  4.                 hmDownloadToSystemAlbum
  5.         } from "@/uni_modules/ha-downloadToSystemAlbum"
  6.         // #endif
复制代码
2. 调用

  1. methods: {
  2.         downloadToSystemAlbum(payload) {
  3.                 // 下载并保存
  4.                 hmDownloadToSystemAlbum({
  5.                         fullUrl: payload.downloadUrl, // 完整下载链接
  6.                         renameUrl: payload.renameUrl, // 下载文件重命名
  7.                         fileType: payload.fileType, // 下载媒体文件类型 'photo' | 'video'
  8.                         progress: (res) => { // 下载进度条
  9.                                 console.log('已下载' + res * 1 + '%');
  10.                         },
  11.                         fail: (err) => { // 下载失败
  12.                                 if (err) {
  13.                                         console.log('下载失败');
  14.                                 }
  15.                         },
  16.                 });
  17.         },
  18. }  
复制代码
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

农民

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表