HarmonyOS Next 应用元服务开发-分布式数据对象迁移数据文件资产迁移

鸿蒙时代
发布于 2024-12-24 10:09
浏览
0收藏

文件资产迁移,对于图片、文档等文件类数据,需要先将其转换为资产commonType.Asset类型,再封装到分布式数据对象中进行迁移。迁移实现方式与普通的分布式数据对象类似,下面仅针对差异部分进行说明。

在源端,将需要迁移的文件资产保存到分布式数据对象DataObject中,执行流程如下:
将文件资产拷贝到分布式文件目录下,相关接口与用法详见基础文件接口。
使用分布式文件目录下的文件创建Asset资产对象。
将Asset资产对象作为分布式数据对象的根属性保存。
随后,与普通数据对象的迁移的源端实现相同,可以使用该数据对象加入组网,并进行持久化保存。

示例如下:

// 导入模块
import { UIAbility, AbilityConstant } from '@kit.AbilityKit';
import { distributedDataObject, commonType } from '@kit.ArkData';
import { fileIo, fileUri } from '@kit.CoreFileKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { BusinessError } from '@ohos.base';
const TAG: string = '[MigrationAbility]';
const DOMAIN_NUMBER: number = 0xFF00;

// 数据对象定义
class ParentObject {
  mother: string
  father: string

  constructor(mother: string, father: string) {
    this.mother = mother
    this.father = father
  }
}

class SourceObject {
  name: string | undefined
  age: number | undefined
  isVis: boolean | undefined
  parent: ParentObject | undefined
  attachment: commonType.Asset | undefined  // 新增资产属性

  constructor(name: string | undefined, age: number | undefined, isVis: boolean | undefined,
    parent: ParentObject | undefined, attachment: commonType.Asset | undefined) {
    this.name = name
    this.age = age
    this.isVis = isVis
    this.parent = parent
    this.attachment = attachment;
  }
}

export default class MigrationAbility extends UIAbility {
  d_object?: distributedDataObject.DataObject;

  async onContinue(wantParam: Record<string, Object>): Promise<AbilityConstant.OnContinueResult> {
    // ...

    // 1. 将资产写入分布式文件目录下
    let distributedDir: string = this.context.distributedFilesDir;  // 获取分布式文件目录路径
    let fileName: string = '/test.txt';                        // 文件名
    let filePath: string = distributedDir + fileName;          // 文件路径

    try {
      // 在分布式目录下创建文件
      let file = fileIo.openSync(filePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);
      hilog.info(DOMAIN_NUMBER, TAG, 'Create file success.');
      // 向文件中写入内容(若资产为图片,可将图片转换为buffer后写入)
      fileIo.writeSync(file.fd, '[Sample] Insert file content here.');
      // 关闭文件
      fileIo.closeSync(file.fd);
    } catch (error) {
      let err: BusinessError = error as BusinessError;
      hilog.error(DOMAIN_NUMBER, TAG, `Failed to openSync / writeSync / closeSync. Code: ${err.code}, message: ${err.message}`);
    }

    // 2. 使用分布式文件目录下的文件创建资产对象
    let distributedUri: string = fileUri.getUriFromPath(filePath); // 获取分布式文件Uri

    // 获取文件参数
    let ctime: string = '';
    let mtime: string = '';
    let size: string = '';
    await fileIo.stat(filePath).then((stat: fileIo.Stat) => {
      ctime = stat.ctime.toString();  // 创建时间
      mtime = stat.mtime.toString();  // 修改时间
      size = stat.size.toString();    // 文件大小
    })

    // 创建资产对象
    let attachment: commonType.Asset = {
      name: fileName,
      uri: distributedUri,
      path: filePath,
      createTime: ctime,
      modifyTime: mtime,
      size: size,
    }

    // 3. 将资产对象作为分布式数据对象的根属性,创建分布式数据对象
    let parentSource: ParentObject = new ParentObject('jack mom', 'jack Dad');
    let source: SourceObject = new SourceObject("jack", 18, false, parentSource, attachment);
    this.d_object = distributedDataObject.create(this.context, source);

    // 生成组网id,激活分布式数据对象,save持久化保存
    // ...
}

对端需要先创建一个各属性为空的Asset资产对象作为分布式数据对象的根属性。在接收到on()接口status为restored的事件的回调时,表示包括资产在内的数据同步完成,可以像获取基本数据一样获取到源端的资产对象。
说明
对端创建分布式数据对象时,SourceObject对象中的资产不能直接使用undefined初始化,需要创建一个各属性为空的Asset资产对象,否则会导致资产同步失败。

示例代码如下:

import { UIAbility, Want } from '@kit.AbilityKit';
import { distributedDataObject, commonType } from '@kit.ArkData';
import { hilog } from '@kit.PerformanceAnalysisKit';
const TAG: string = '[MigrationAbility]';
const DOMAIN_NUMBER: number = 0xFF00;

export default class MigrationAbility extends UIAbility {
  d_object?: distributedDataObject.DataObject;

  handleDistributedData(want: Want) {
    // ...
    // 创建一个各属性为空的资产对象
    let attachment: commonType.Asset = {
      name: '',
      uri: '',
      path: '',
      createTime: '',
      modifyTime: '',
      size: '',
    }

    // 使用该空资产对象创建分布式数据对象,其余基础属性可以直接使用undefined
    let source: SourceObject = new SourceObject(undefined, undefined, undefined, undefined, attachment);
    this.d_object = distributedDataObject.create(this.context, source);

    this.d_object.on("status", (sessionId: string, networkId: string, status: 'online' | 'offline' | 'restored') => {
        if (status == 'restored') {
          // 收到监听的restored回调,表示分布式资产对象同步完成
          hilog.info(DOMAIN_NUMBER, TAG, "restored attachment:" + JSON.stringify(this.d_object['attachment']));
        }
    });
    // ...
  }
}

若应用想要同步多个资产,可采用两种方式实现:

可将每个资产作为分布式数据对象的一个根属性实现,适用于要迁移的资产数量固定的场景。
可以将资产数组传化为Object传递,适用于需要迁移的资产个数会动态变化的场景(如用户选择了不定数量的图片)。当前不支持直接将资产数组作为根属性传递。
其中方式1的实现可以直接参照添加一个资产的方式添加更多资产。方式2的示例如下所示:

// 导入模块
import { distributedDataObject, commonType } from '@kit.ArkData';
import { UIAbility } from '@kit.AbilityKit';

// 数据对象定义
class SourceObject {
  name: string | undefined
  assets: Object | undefined  // 分布式数据对象的中添加一个Object属性

  constructor(name: string | undefined, assets: Object | undefined) {
    this.name = name
    this.assets = assets;
  }
}

// 该函数用于将资产数组转为Record
GetAssetsWrapper(assets: commonType.Assets): Record<string, commonType.Asset> {
  let wrapper: Record<string, commonType.Asset> = {}
  let num: number = assets.length;
  for (let i: number = 0; i < num; i++) {
    wrapper[`asset${i}`] = assets[i];
  }
  return wrapper;
}

export default class MigrationAbility extends UIAbility {
  d_object?: distributedDataObject.DataObject;

  async onContinue(wantParam: Record<string, Object>): AbilityConstant.OnContinueResult {
    // ...

    // 创建了多个资产对象
    let attachment1: commonType.Asset = {
      // ...
    }

    let attachment2: commonType.Asset = {
      // ...
    }

    // 将资产对象插入资产数组
    let assets: commonType.Assets = [];
    assets.push(attachment1);
    assets.push(attachment2);

    // 将资产数组转为Record Object,并用于创建分布式数据对象
    let assetsWrapper: Object = this.GetAssetsWrapper(assets);
    let source: SourceObject = new SourceObject("jack", assetsWrapper);
    this.d_object = distributedDataObject.create(this.context, source);

    // ...
}

本文主要引用HarmonyOS官方文档

分类
收藏
回复
举报
回复
    相关推荐