HarmonyOS Next 应用元服务开发-分布式数据对象迁移数据文件资产迁移
文件资产迁移,对于图片、文档等文件类数据,需要先将其转换为资产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官方文档