鸿蒙跨设备文件传输系统:基于分布式文件服务的实现方案 原创

进修的泡芙
发布于 2025-6-18 22:12
浏览
0收藏

鸿蒙跨设备文件传输系统:基于分布式文件服务的实现方案

本文将详细介绍如何使用HarmonyOS的分布式文件服务能力,构建一个高效、安全的多设备文件传输系统,实现设备间的文件共享和同步。

技术架构
文件管理层:使用分布式文件系统API访问文件

设备发现层:通过分布式设备管理发现周边设备

传输控制层:管理文件传输队列和状态

UI展示层:文件选择界面和传输进度展示

完整代码实现
设备模型定义

// model/DeviceInfo.ts
export class DeviceInfo {
deviceId: string = ‘’; // 设备ID
deviceName: string = ‘’; // 设备名称
deviceType: string = ‘’; // 设备类型
isConnected: boolean = false; // 是否已连接

constructor(data?: Partial<DeviceInfo>) {
if (data) {
Object.assign(this, data);
}

文件传输任务模型

// model/FileTransferTask.ts
export class FileTransferTask {
taskId: string = ‘’; // 任务ID
fileName: string = ‘’; // 文件名
fileSize: number = 0; // 文件大小(字节)
filePath: string = ‘’; // 文件路径
targetDeviceId: string = ‘’; // 目标设备ID
status: ‘pending’ ‘transferring’ ‘completed’
‘failed’ = ‘pending’;
progress: number = 0; // 传输进度(0-100)
startTime: number = 0; // 开始时间戳
endTime: number = 0; // 结束时间戳

constructor(data?: Partial<FileTransferTask>) {
if (data) {
Object.assign(this, data);
if (!this.taskId) {
this.taskId = this.generateTaskId();
if (!this.startTime) {

    this.startTime = Date.now();

}

private generateTaskId(): string {

return 'task-' + Date.now() + '-' + Math.random().toString(36).substr(2, 6);

// 获取传输速度(字节/秒)

get transferSpeed(): number {
if (this.status !== ‘transferring’ || this.progress <= 0) return 0;
const elapsedTime = (Date.now() - this.startTime) / 1000;
return Math.floor((this.fileSize * this.progress / 100) / elapsedTime);
// 格式化文件大小

get formattedSize(): string {
if (this.fileSize < 1024) return ${this.fileSize} B;
if (this.fileSize < 1024 * 1024) return ${(this.fileSize / 1024).toFixed(2)} KB;
if (this.fileSize < 1024 1024 1024) return ${(this.fileSize / (1024 * 1024)).toFixed(2)} MB;
return ${(this.fileSize / (1024 1024 1024)).toFixed(2)} GB;
}

分布式文件服务实现

// service/DistributedFileService.ts
import distributedFile from ‘@ohos.distributedFile’;
import deviceManager from ‘@ohos.distributedHardware.deviceManager’;
import { DeviceInfo } from ‘…/model/DeviceInfo’;
import { FileTransferTask } from ‘…/model/FileTransferTask’;

const SERVICE_ID = ‘file_transfer_service’;

export class DistributedFileService {
private deviceManager: deviceManager.DeviceManager;
private discoveredDevices: Map<string, DeviceInfo> = new Map();
private transferTasks: Map<string, FileTransferTask> = new Map();
private transferCallbacks: Map<string, (task: FileTransferTask) => void> = new Map();

// 初始化服务
async initialize() {
try {
this.deviceManager = await deviceManager.createDeviceManager(‘com.example.filetransfer’);
this.setupDeviceListeners();
await this.startDiscovery();
catch (err) {

  console.error('初始化分布式文件服务失败:', err);

}

// 设置设备监听器
private setupDeviceListeners() {
this.deviceManager.on(‘deviceStateChange’, (data) => {
const deviceId = data.device.deviceId;
if (data.state === ‘online’) {
this.addDiscoveredDevice(data.device);
else {

    this.removeDiscoveredDevice(deviceId);

});

this.deviceManager.on('deviceFound', (data) => {
  this.addDiscoveredDevice(data.device);
});

// 开始设备发现

private async startDiscovery() {
try {
await this.deviceManager.startDeviceDiscovery([SERVICE_ID]);
catch (err) {

  console.error('启动设备发现失败:', err);

}

// 添加发现的设备
private addDiscoveredDevice(device: any) {
const deviceInfo = new DeviceInfo({
deviceId: device.deviceId,
deviceName: device.deviceName,
deviceType: device.deviceType,
isConnected: false
});
this.discoveredDevices.set(device.deviceId, deviceInfo);
this.notifyDevicesUpdated();
// 移除设备

private removeDiscoveredDevice(deviceId: string) {
this.discoveredDevices.delete(deviceId);
this.notifyDevicesUpdated();
// 通知设备列表更新

private notifyDevicesUpdated() {
const devices = Array.from(this.discoveredDevices.values());
AppStorage.setOrCreate(‘discoveredDevices’, devices);
// 连接设备

async connectDevice(deviceId: string): Promise<boolean> {
try {
const device = this.discoveredDevices.get(deviceId);
if (!device) return false;

  await this.deviceManager.authenticateDevice(deviceId);
  device.isConnected = true;
  this.discoveredDevices.set(deviceId, device);
  this.notifyDevicesUpdated();
  return true;

catch (err) {

  console.error('连接设备失败:', err);
  return false;

}

// 发送文件
async sendFile(fileUri: string, targetDeviceId: string): Promise<FileTransferTask> {
const fileInfo = await this.getFileInfo(fileUri);
const task = new FileTransferTask({
fileName: fileInfo.name,
fileSize: fileInfo.size,
filePath: fileUri,
targetDeviceId: targetDeviceId
});

this.transferTasks.set(task.taskId, task);
this.notifyTaskUpdated(task);

// 开始传输
this.startFileTransfer(task);
return task;

// 获取文件信息

private async getFileInfo(fileUri: string): Promise<{name: string, size: number}> {
try {
const file = await distributedFile.open(fileUri, distributedFile.OpenMode.READ_ONLY);
const stat = await file.stat();
await file.close();
return {
name: fileUri.split(‘/’).pop() || ‘unknown’,
size: stat.size
};
catch (err) {

  console.error('获取文件信息失败:', err);
  throw err;

}

// 开始文件传输
private async startFileTransfer(task: FileTransferTask) {
try {
task.status = ‘transferring’;
this.notifyTaskUpdated(task);

  const sendOptions = {
    targetDeviceId: task.targetDeviceId,
    fileUri: task.filePath,
    onProgress: (progress: number) => {
      task.progress = progress;
      this.notifyTaskUpdated(task);

};

  await distributedFile.send(sendOptions);

  task.status = 'completed';
  task.progress = 100;
  task.endTime = Date.now();
  this.notifyTaskUpdated(task);

catch (err) {

  console.error('文件传输失败:', err);
  task.status = 'failed';
  this.notifyTaskUpdated(task);

}

// 通知任务更新
private notifyTaskUpdated(task: FileTransferTask) {
this.transferTasks.set(task.taskId, task);
AppStorage.setOrCreate(‘transferTasks’, Array.from(this.transferTasks.values()));

const callback = this.transferCallbacks.get(task.taskId);
if (callback) {
  callback(task);

}

// 注册任务更新回调
registerTaskCallback(taskId: string, callback: (task: FileTransferTask) => void) {
this.transferCallbacks.set(taskId, callback);
// 清理资源

cleanup() {
this.deviceManager.off(‘deviceStateChange’);
this.deviceManager.off(‘deviceFound’);
this.deviceManager.release();
}

文件选择器组件

// components/FilePicker.ets
import { DeviceInfo } from ‘…/model/DeviceInfo’;

@Component
export struct FilePicker {
@State selectedFiles: string[] = [];
@State isSelecting: boolean = false;
@Link discoveredDevices: DeviceInfo[];
@State selectedDeviceId: string = ‘’;

build() {
Column() {
// 文件选择按钮
Button(‘选择文件’)
.width(200)
.onClick(() => {
this.openFilePicker();
})

  // 已选文件列表
  if (this.selectedFiles.length > 0) {
    Text('已选文件:')
      .fontSize(16)
      .margin({ top: 16 })
    
    ForEach(this.selectedFiles, (file) => {
      Text(file.split('/').pop() || '')
        .fontSize(14)
        .margin({ top: 8 })
    })

// 设备选择下拉框

  if (this.selectedFiles.length > 0 && this.discoveredDevices.length > 0) {
    Text('选择目标设备:')
      .fontSize(16)
      .margin({ top: 20 })
    
    Select(this.discoveredDevices.map(device => ({
      value: device.deviceId,
      label: {device.deviceName} ({device.deviceType})
    })))
    .onSelect((value: string) => {
      this.selectedDeviceId = value;
    })
    .margin({ top: 8 })

// 发送按钮

  if (this.selectedFiles.length > 0 && this.selectedDeviceId) {
    Button('发送文件')
      .width(200)
      .margin({ top: 20 })
      .onClick(() => {
        this.sendFiles();
      })

}

.padding(16)

// 打开文件选择器

private async openFilePicker() {
try {
this.isSelecting = true;
const fileUris = await filePicker.pickFiles({
multiple: true,
fileTypes: [‘/’]
});
this.selectedFiles = fileUris;
catch (err) {

  console.error('选择文件失败:', err);

finally {

  this.isSelecting = false;

}

// 发送文件
private async sendFiles() {
if (!this.selectedDeviceId || this.selectedFiles.length === 0) return;

const fileService = new DistributedFileService();
await fileService.initialize();

// 连接设备
const connected = await fileService.connectDevice(this.selectedDeviceId);
if (!connected) {
  prompt.showToast({ message: '连接设备失败', duration: 3000 });
  return;

// 发送每个文件

for (const fileUri of this.selectedFiles) {
  await fileService.sendFile(fileUri, this.selectedDeviceId);

}

文件传输页面实现

// pages/FileTransferPage.ets
import { DistributedFileService } from ‘…/service/DistributedFileService’;
import { FileTransferTask } from ‘…/model/FileTransferTask’;
import { FilePicker } from ‘…/components/FilePicker’;

@Entry
@Component
struct FileTransferPage {
private fileService: DistributedFileService = new DistributedFileService();
@StorageLink(‘discoveredDevices’) discoveredDevices: DeviceInfo[] = [];
@StorageLink(‘transferTasks’) transferTasks: FileTransferTask[] = [];
@State activeTab: ‘send’ | ‘receive’ = ‘send’;

async aboutToAppear() {
await this.fileService.initialize();
onPageHide() {

this.fileService.cleanup();

build() {

Column() {
  // 选项卡
  Tabs({ barPosition: BarPosition.Start }) {
    TabContent('发送文件') {
      this.buildSendTab()

.tabBar(‘发送’)

    TabContent('接收文件') {
      this.buildReceiveTab()

.tabBar(‘接收’)

.barWidth(‘100%’)

  .barHeight(50)
  .width('100%')
  .height('100%')

}

@Builder
buildSendTab() {
Column() {
FilePicker({
discoveredDevices: $discoveredDevices
})

  // 传输任务列表
  if (this.transferTasks.length > 0) {
    Text('传输任务:')
      .fontSize(18)
      .fontWeight(FontWeight.Bold)
      .margin({ top: 20, bottom: 10 })
    
    List() {
      ForEach(this.transferTasks, (task) => {
        ListItem() {
          TransferTaskItem({ task })

})

.layoutWeight(1)

    .width('100%')

}

.width('100%')
.height('100%')
.padding(16)

@Builder

buildReceiveTab() {
Column() {
Text(‘接收到的文件将显示在这里’)
.fontSize(16)
.margin({ top: 20 })

  // 这里可以添加接收文件列表的实现

.width(‘100%’)

.height('100%')
.justifyContent(FlexAlign.Center)

}

@Component
struct TransferTaskItem {
@Prop task: FileTransferTask;

build() {
Column() {
Row() {
Text(this.task.fileName)
.fontSize(16)
.layoutWeight(1)

    Text(${this.task.progress}%)
      .fontSize(14)
      .fontColor('#666666')

.width(‘100%’)

  Row() {
    Text(大小: ${this.task.formattedSize})
      .fontSize(12)
      .fontColor('#888888')
      .layoutWeight(1)
    
    Text(this.getStatusText())
      .fontSize(12)
      .fontColor(this.getStatusColor())

.width(‘100%’)

  .margin({ top: 4 })
  
  Progress({
    value: this.task.progress,
    total: 100,
    style: ProgressStyle.Linear
  })
  .width('100%')
  .margin({ top: 8 })

.padding(12)

.width('100%')
.backgroundColor('#F5F5F5')
.borderRadius(8)
.margin({ bottom: 8 })

private getStatusText(): string {

switch (this.task.status) {
  case 'pending': return '等待中';
  case 'transferring': return 传输中 (${this.formatSpeed(this.task.transferSpeed)});
  case 'completed': return '已完成';
  case 'failed': return '失败';
  default: return '';

}

private getStatusColor(): string {
switch (this.task.status) {
case ‘completed’: return ‘#4CAF50’;
case ‘failed’: return ‘#F44336’;
case ‘transferring’: return ‘#2196F3’;
default: return ‘#666666’;
}

private formatSpeed(bytesPerSec: number): string {
if (bytesPerSec < 1024) return ${bytesPerSec} B/s;
if (bytesPerSec < 1024 * 1024) return ${(bytesPerSec / 1024).toFixed(1)} KB/s;
return ${(bytesPerSec / (1024 * 1024)).toFixed(1)} MB/s;
}

实现原理详解
设备发现机制:

使用DeviceManager发现周边设备

监听设备状态变化(上线/下线)

维护已发现设备列表
文件传输流程:

选择本地文件和目标设备

建立设备间安全连接

通过分布式文件服务传输文件

实时更新传输进度
任务管理:

跟踪每个传输任务的状态

计算传输速度和剩余时间

处理传输成功/失败情况

扩展功能建议
断点续传支持:

  // 添加断点续传功能

async resumeTransfer(taskId: string) {
const task = this.transferTasks.get(taskId);
if (task?.status === ‘failed’) {
await this.startFileTransfer(task);
}

文件加密传输:

  // 添加文件加密

async encryptAndSend(fileUri: string, targetDeviceId: string) {
const encryptedFile = await this.encryptFile(fileUri);
return this.sendFile(encryptedFile, targetDeviceId);

多文件批量传输:

  // 批量传输多个文件

async sendMultipleFiles(fileUris: string[], targetDeviceId: string) {
const tasks = [];
for (const fileUri of fileUris) {
tasks.push(this.sendFile(fileUri, targetDeviceId));
return Promise.all(tasks);

总结

本文详细介绍了如何利用HarmonyOS的分布式文件服务能力构建一个多设备文件传输系统。通过设备发现、安全连接和高效传输机制,实现了设备间的文件共享功能。该系统具有以下特点:
跨设备能力:支持不同鸿蒙设备间的文件传输

高效传输:利用分布式技术实现快速文件共享

安全可靠:基于HarmonyOS的安全机制保障数据传输

实时反馈:提供详细的传输进度和状态信息

这种架构不仅适用于文件传输场景,也可以扩展到数据同步、备份恢复等多种分布式应用场景。合理利用鸿蒙的分布式能力,可以大大提升多设备协同工作的效率和用户体验。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
    相关推荐