鸿蒙 分布式文件-跨设备文件拷贝(三)
摘要:本文介绍了基于分布式文件系统实现跨设备文件拷贝的开发流程。关键步骤包括:1)设备组网需登录同一账号并开启蓝牙/Wi-Fi;2)动态申请DISTRIBUTED_DATASYNC权限;3)通过分布式目录中转文件,设备A将文件拷贝至本地分布式目录,设备B从中获取;4)使用connectDfs/disconnectDfs管理连接。注意事项包括中转目录使用规范、临时文件清理要求,以及权限管理机制。该方
本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
-
分布式文件系统为应用提供跨设备文件拷贝的能力
-
可以通过基础文件接口进行跨设备拷贝文件
应用场景
多设备数据流转:
-
设备组网互联之后,设备A上的应用可将沙箱文件拷贝到设备A的分布式目录下
-
设备B在粘贴时,从B设备的分布式目录下将文件拷贝到对应的沙箱文件中
二、开发步骤
2.1 步骤一:完成分布式组网
-
两个设备登录同一账号
-
保证设备蓝牙和Wi-Fi功能开启
-
蓝牙无需互连
-
Wi-Fi无需接入同一个局域网
2.2 步骤二:授权分布式数据同步权限
-
权限名称:
ohos.permission.DISTRIBUTED_DATASYNC -
授权方式:user_grant(需要用户动态授权)
-
申请方式:调用
requestPermissionsFromUser接口 -
交互形式:动态弹窗方式向用户申请授权
代码实现:
import { common, abilityAccessCtrl } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
let atManager = abilityAccessCtrl.createAtManager();
try {
// 以动态弹窗的方式向用户申请授权
atManager.requestPermissionsFromUser(context, ['ohos.permission.DISTRIBUTED_DATASYNC'])
.then((result) => {
console.info(`request permission result: ${JSON.stringify(result)}`);
}).catch((err: BusinessError) => {
console.error(`Failed to request permissions from user. Code: ${err.code}, message: ${err.message}`);
});
} catch (error) {
let err: BusinessError = error as BusinessError;
console.error(`Catch err. Failed to request permissions from user. Code: ${err.code}, message: ${err.message}`);
}
2.3 步骤三:执行跨设备文件拷贝
核心机制:
-
同一应用在不同设备之间实现跨设备文件拷贝
-
只需要将对应的文件放在应用沙箱的分布式目录即可
2.3.1 设备A:将待拷贝沙箱文件拷贝到分布式目录
文件路径说明:
-
context.filesDir:应用沙箱目录 -
context.distributedFilesDir:应用分布式目录
代码实现:
import { fileIo as fs } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { fileUri } from '@kit.CoreFileKit';
let pathDir: string = context.filesDir;
let distributedPathDir: string = context.distributedFilesDir;
// 待拷贝文件沙箱路径
let filePath: string = pathDir + '/src.txt';
try {
// 准备待拷贝沙箱文件
let file = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
fs.writeSync(file.fd, 'Create file success');
fs.closeSync(file);
} catch (error) {
console.error(`Failed to createFile. Code: ${error.code}, message: ${error.message}`);
}
// 获取待拷贝源文件uri
let srcUri = fileUri.getUriFromPath(filePath);
// 获取目标路径(分布式目录)的uri
let destUri: string = fileUri.getUriFromPath(distributedPathDir + '/src.txt');
try {
// 将沙箱路径下的源文件拷贝到目标分布式目录下
fs.copy(srcUri, destUri).then(() => {
console.info(`Succeeded in copying---. `);
console.info(`src: ${srcUri} dest: ${destUri}`);
}).catch((error: BusinessError) => {
let err: BusinessError = error as BusinessError;
console.error(`Failed to copy. Code: ${err.code}, message: ${err.message}`);
});
} catch (error) {
console.error(`Catch err. Failed to copy. Code: ${error.code}, message: ${error.message}`);
}
2.3.2 设备B:从分布式目录拷贝文件到沙箱
流程:
-
获取设备A的networkId
-
连接分布式文件系统
-
从分布式目录拷贝文件
-
清理分布式目录下的临时文件
代码实现:
import { fileIo as fs } from '@kit.CoreFileKit';
import { common } from '@kit.AbilityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { fileUri } from '@kit.CoreFileKit';
import { distributedDeviceManager } from '@kit.DistributedServiceKit';
// ...
let pathDir: string = context.filesDir;
let distributedPathDir: string = context.distributedFilesDir;
// 待拷贝文件的目标路径(沙箱路径)
let destPath: string = pathDir + '/dest.txt';
// 获取目标路径uri
let destUri = fileUri.getUriFromPath(destPath);
// 拷贝源文件路径(分布式目录)
let srcPath = distributedPathDir + '/src.txt';
// 获取源路径uri
let srcUri: string = fileUri.getUriFromPath(srcPath);
// 定义拷贝回调
let progressListener: fs.ProgressListener = (progress: fs.Progress) => {
console.info(`progressSize: ${progress.processedSize}, totalSize: ${progress.totalSize}`);
};
let options: fs.CopyOptions = {
'progressListener': progressListener
};
// 通过分布式设备管理的接口获取设备A的networkId信息
let dmInstance = distributedDeviceManager.createDeviceManager('com.example.hap');
let deviceInfoList: distributedDeviceManager.DeviceBasicInfo[] = dmInstance.getAvailableDeviceListSync();
if (deviceInfoList && deviceInfoList.length > 0) {
console.info(`success to get available device list`);
// 这里只是两个设备连接,列表中首个即为A设备的networkId
let networkId = deviceInfoList[0].networkId;
// 定义访问分布式目录的回调
let listeners: fs.DfsListeners = {
onStatus: (networkId: string, status: number): void => {
console.error(`Failed to access public directory,${status}`);
}
};
// 开始跨设备文件拷贝
fs.connectDfs(networkId, listeners).then(() => {
try {
// 将分布式目录下的文件拷贝到其他沙箱路径下
fs.copy(srcUri, destUri, options).then(() => {
console.info(`Succeeded in copying from distribted path`);
console.info(`src: ${srcUri} dest: ${destUri}`);
// 拷贝完成后清理分布式目录下的临时文件
fs.unlinkSync(srcPath);
}).catch((error: BusinessError) => {
let err: BusinessError = error as BusinessError;
console.error(`Failed to copy. Code: ${err.code}, message: ${err.message}`);
});
} catch (error) {
console.error(`Catch err. Failed to copy. Code: ${error.code}, message: ${error.message}`);
}
}).catch((error: BusinessError) => {
let err: BusinessError = error as BusinessError;
console.error(`Failed to connect dfs. Code: ${err.code}, message: ${err.message}`);
});
}
2.4 步骤四:断开链路
跨设备文件拷贝完成后,需要断开分布式文件系统连接
代码实现:
import { BusinessError } from '@kit.BasicServicesKit';
import { distributedDeviceManager } from '@kit.DistributedServiceKit';
import { fileIo as fs } from '@kit.CoreFileKit';
// 获取设备A的networkId
// ...
let dmInstance = distributedDeviceManager.createDeviceManager('com.example.hap');
let deviceInfoList: distributedDeviceManager.DeviceBasicInfo[] = dmInstance.getAvailableDeviceListSync();
if (deviceInfoList && deviceInfoList.length > 0) {
console.info(`Success to get available device list`);
let networkId = deviceInfoList[0].networkId;
// 关闭跨设备文件访问
fs.disconnectDfs(networkId).then(() => {
console.info(`Success to disconnect dfs`);
}).catch((err: BusinessError) => {
console.error(`Failed to disconnect dfs. Code: ${err.code}, message: ${err.message}`);
});
}
三、相关API总结
3.1 权限申请相关
| API | 功能 | 所属模块 |
|---|---|---|
abilityAccessCtrl.createAtManager() |
创建访问控制管理器 | @kit.AbilityKit |
requestPermissionsFromUser() |
动态申请用户权限 | @kit.AbilityKit |
3.2 文件操作相关
| API | 功能 | 所属模块 |
|---|---|---|
fs.openSync() |
打开文件 | @kit.CoreFileKit |
fs.writeSync() |
写入文件 | @kit.CoreFileKit |
fs.closeSync() |
关闭文件 | @kit.CoreFileKit |
fs.copy() |
拷贝文件 | @kit.CoreFileKit |
fs.unlinkSync() |
删除文件 | @kit.CoreFileKit |
3.3 分布式文件系统相关
| API | 功能 | 所属模块 |
|---|---|---|
context.distributedFilesDir |
获取分布式目录路径 | @kit.AbilityKit |
fileUri.getUriFromPath() |
从路径获取URI | @kit.CoreFileKit |
fs.connectDfs() |
连接分布式文件系统 | @kit.CoreFileKit |
fs.disconnectDfs() |
断开分布式文件系统 | @kit.CoreFileKit |
fs.DfsListeners |
分布式文件访问状态监听 | @kit.CoreFileKit |
fs.ProgressListener |
拷贝进度监听 | @kit.CoreFileKit |
fs.CopyOptions |
拷贝选项配置 | @kit.CoreFileKit |
3.4 设备管理相关
| API | 功能 | 所属模块 |
|---|---|---|
distributedDeviceManager.createDeviceManager() |
创建设备管理器 | @kit.DistributedServiceKit |
getAvailableDeviceListSync() |
同步获取可用设备列表 | @kit.DistributedServiceKit |
DeviceBasicInfo.networkId |
设备网络ID | @kit.DistributedServiceKit |
四、完整流程
设备A 设备B
| |
|-- 1. 创建沙箱文件 |
|-- 2. 拷贝到分布式目录 |
| (fs.copy) |
| |
| |-- 3. 获取设备A的networkId
| | (getAvailableDeviceListSync)
| |
| |-- 4. 连接分布式文件系统
| | (fs.connectDfs)
| |
| |-- 5. 从分布式目录拷贝文件
| | (fs.copy + ProgressListener)
| |
| |-- 6. 清理分布式目录临时文件
| | (fs.unlinkSync)
| |
| |-- 7. 断开分布式文件系统连接
| | (fs.disconnectDfs)
五、注意事项
5.1 组网
-
两个设备必须登录同一华为账号
-
蓝牙和Wi-Fi功能必须开启
-
蓝牙不需要互连
-
Wi-Fi不需要接入同一个局域网
5.2 权限
-
必须动态申请
ohos.permission.DISTRIBUTED_DATASYNC权限 -
权限类型为user_grant,需要用户通过弹窗授权
-
未授权时无法进行跨设备文件操作
5.3 目录说明
-
分布式目录:
context.distributedFilesDir,跨设备文件共享的中转目录 -
沙箱目录:
context.filesDir,应用私有文件目录 -
跨设备文件拷贝必须通过分布式目录进行中转
5.4 操作规范
-
设备A:将沙箱文件拷贝到本机分布式目录
-
设备B:从本机分布式目录拷贝文件到沙箱目录
-
临时文件清理:拷贝完成后需要清理分布式目录下的临时文件(
fs.unlinkSync) -
连接管理:跨设备操作前需要
connectDfs,操作完成后需要disconnectDfs
本质
-
不是直接设备到设备的拷贝
-
而是通过各自设备的分布式目录作为中转
-
设备A:沙箱 → 分布式目录(本地操作)
-
设备B:分布式目录 → 沙箱(本地操作)
更多推荐

所有评论(0)