鸿蒙系统分布式文件概述、访问、拷贝

1. 分布式文件系统概述

分布式文件系统(hmdfs,HarmonyOS Distributed File System)提供跨设备的文件访问能力,适用于如下场景:

  • 两台设备组网,用户可以利用一台设备上的编辑软件编辑另外一台设备上的文档。

  • 平板保存的音乐,车载系统直接可见并可播放。

  • 户外拍摄的照片,回家打开平板直接访问原设备拍摄的照片。

hmdfs在分布式软总线动态组网的基础上,为网络上各个设备结点提供一个全局一致的访问视图,支持开发者通过基础文件系统的接口进行读写访问,具有高性能、低延时等优点。

2. 设置分布式文件等级

不同设备本身的安全能力差异较大,因此,HarmonyOS提供一套完整的数据分级、设备分级标准,并针对不同设备制定不同的数据流转策略。

官方提供的API:setSecurityLabel

使用方式:

javascript 复制代码
//打开文件
let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
// 设置文件的数据等级为s0
securityLabel.setSecurityLabel(filePath, 's0').then(() => {
  console.info('Succeeded in setSecurityLabeling.');
  fs.closeSync(file);
}).catch((err: BusinessError) => {
  console.error(`Failed to setSecurityLabel. Code: ${err.code}, message: ${err.message}`);
});

3. 跨设备文件访问

分布式文件系统为应用提供了跨设备文件访问的能力,开发者在两个设备安装同一应用时,通过基础文件接口,可跨设备读写另一个设备该应用分布式文件路径(/data/storage/el2/distributedfiles/)下的文件。例如:多设备数据流转的场景,设备组网互联之后,设备A上的应用可访问设备B同应用分布式路径下的文件,当期望应用文件被其他设备访问时,只需将文件移动到分布式文件路径即可。

使用步骤:

1. 完成组网

将需要跨设备访问的两个设备登录同一账号,保证设备蓝牙和Wi-Fi功能开启,蓝牙无需互连,Wi-Fi无需接入同一个局域网。

2. 访问跨设备文件

同一应用不同设备之间实现跨设备文件访问,只需要将对应的文件放在应用沙箱的分布式文件路径即可。

2.1 设备A在分布式下创建文件:
javascript 复制代码
async createDistributedFile(uri: string) {
    let context = getContext(this) as common.UIAbilityContext; 
    let pathDir: string = context.distributedFilesDir;
    // 获取分布式目录的文件路径
    let filePath: string = pathDir + '/test.txt';

    try {
      // 在分布式目录下创建文件
      let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
      console.info('Succeeded in createing.');
      // 向文件中写入内容
      fs.writeSync(file.fd, 'content');
      // 关闭文件
      fs.closeSync(file.fd);
    } catch (error) {
      let err: BusinessError = error as BusinessError;
      console.error(`Failed to openSync / writeSync / closeSync. Code: ${err.code}, message: ${err.message}`);
    }
  }
2.2 设备B在分布式路径下读取文件,并保存到本地
javascript 复制代码
/**
   * 拉起picker保存文件
   */
  async saveFile(fileName: string):Promise<string>{
    // fileName = this.tempFilePath;
    PhLog.info('保存的文件名:' + fileName)
    let saveFileUri = ''
    try {
      let DocumentSaveOptions = new picker.DocumentSaveOptions();
      DocumentSaveOptions.newFileNames = [fileName];
      let documentPicker = new picker.DocumentViewPicker();
      await documentPicker.save(DocumentSaveOptions).then( (DocumentSaveResult) => {
        PhLog.info('DocumentViewPicker.save successfully, DocumentSaveResult uri: ' + JSON.stringify(DocumentSaveResult));
        if (DocumentSaveResult !== null && DocumentSaveResult !== undefined) {
          let uri = DocumentSaveResult[0] as string;
          PhLog.info('分布式',`save file uri: ${uri}`);
          this.realFileUri = uri
          this.realSaveFile(fileName)
          saveFileUri = uri
        }
      }).catch((err: BusinessError) => {
        PhLog.error('saveFile-DocumentViewPicker.save failed with err: ' + JSON.stringify(err));
      });
    } catch (err) {
      PhLog.error('saveFile-DocumentViewPicker failed with err: ' + err);
    }

    return saveFileUri
  }

  realFileUri: string = ''

  /**
   * 真正开始保存文件
   */
  async realSaveFile(fileName: string) {
    // let fileName = this.tempFilePath;
    let context = getContext(this) as common.UIAbilityContext; // 获取设备B的UIAbilityContext信息
    let pathDir = context.distributedFilesDir;
    // 获取分布式目录的文件路径
    let filePath = pathDir + '/' + fileName;
    PhLog.info('保存文件时候读取的文件路径:' + filePath)

    //开始写入内容
    let startSaveFileTask: taskpool.Task = new taskpool.Task(startSaveFile3, filePath,this.realFileUri);

    taskpool.execute(startSaveFileTask).then((writtenSize: number) => {
      if (writtenSize > 0) {
        console.info('分布式',`文件写入成功,写入大小: ${writtenSize} 字节`);
        promptAction.showToast({ message: '文件保存成功' })
      } else {
        console.error('分布式','文件写入失败');
      }
      this.deleteDistributedFile(filePath)
    })


@Concurrent
export async function startSaveFile3(filePath: string, realFileUri: string): Promise<number> {
  try {
    // 读取源文件
    const sourceFile = fs.openSync(filePath, fs.OpenMode.READ_ONLY);
    const stats = await fs.stat(filePath);
    const fileSize = stats.size;

    PhLog.info('分布式', `保存的文件: ${filePath} - 大小:${fileSize}`);

    // 目标文件
    const targetFile = fs.openSync(realFileUri, fs.OpenMode.WRITE_ONLY);

    // 分片大小,可根据实际情况调整
    const chunkSize = 1024 * 1024*20; // 1MB
    let offset = 0;
    let totalWritten = 0;

    while (offset < fileSize) {
      const currentChunkSize = Math.min(chunkSize, fileSize - offset);
      const buffer = new ArrayBuffer(currentChunkSize);
      PhLog.info('分布式','01开始读取:'+s)
      // 读取当前分片的数据
      const readLen = fs.readSync(sourceFile.fd, buffer, { offset });
      if (readLen === 0) {
        break;
      }
      // 写入当前分片的数据
      const writeLen = await fs.write(targetFile.fd, buffer, { offset });
      totalWritten += writeLen;
      offset += writeLen;
      // 计算并调用进度回调
      const progress = (totalWritten / fileSize) * 100;
      PhLog.info('分布式', `写入进度: ${progress.toFixed(2)}%`);
    }

    // 关闭文件
    fs.closeSync(sourceFile);
    fs.closeSync(targetFile);

    return totalWritten;
  } catch (error) {
    PhLog.error('分布式', `保存文件时出错: ${error.message}`);
    return -1;
  }
}
到这里就完成了分布式文件的访问、拷贝,整体流程就是:
  • A设备创建分布式文件,写入内容
  • B设备从分布式文件系统目录上读取文件内容
  • 将文件保存到本地

PS:操作文件时候注意添加相关权限

相关推荐
顾北辰2011 分钟前
分布式中间件:Redis介绍
redis·分布式·中间件
AirDroid_cn26 分钟前
华为手机投屏到Windows电脑,不是华为电脑怎么投屏?
华为·智能手机·电脑·手机投屏·无线投屏·手机投屏电脑
前端晚间课28 分钟前
鸿蒙原生应用开发入门与实践
harmonyos
程序猿阿伟1 小时前
《解锁HarmonyOS NEXT高阶玩法:艺术图像识别功能开发全攻略》
华为·harmonyos
敢嗣先锋1 小时前
鸿蒙5.0实战案例:基于原生能力获取视频缩略图
移动开发·harmonyos·arkui·组件化·鸿蒙开发
敢嗣先锋1 小时前
鸿蒙5.0实战案例:基于hvigor插件定制构建
移动开发·harmonyos·arkts·arkui·组件化·鸿蒙开发·hvigor
冰火同学1 小时前
简述Spark的宽窄依赖以及Stage是怎么划分的以及每个stage又是怎么划分task任务数
大数据·分布式·spark
WeiLai11122 小时前
面试基础---Spring Cloud微服务负载均衡架构
spring boot·分布式·后端·spring·spring cloud·面试·架构
深圳深光标准技术2 小时前
开放鸿蒙认证,OpenHarmony兼容性认证介绍
华为·开放原子·harmonyos·鸿蒙系统·开源鸿蒙
怪咖码农3 小时前
RabbitMQ怎么实现延时支付?
java·分布式·rabbitmq