引言

文件上传下载是移动应用中最常见的网络操作之一——从更新包的静默下载到头像图片的上传,从离线内容包的获取到日志文件的回传。HarmonyOS NEXT 通过 @ohos.request 模块将上传下载能力统一封装为任务对象,提供完整的进度监听、暂停恢复和取消删除等生命周期管理。

@ohos.request 属于 @kit.BasicServicesKit,是系统级文件传输代理(File Transfer Agent)的统一入口。与 Android 的 DownloadManager + HttpURLConnection(分散在两个 API 中)和 iOS 的 URLSession(后台会话配置复杂)不同,鸿蒙将上传和下载整合到一个模块中,通过 DownloadTaskUploadTask 两个任务对象提供一致的 Promise + on/off 事件回调模型。

本文将深入讲解 @ohos.request 的文件下载、进度监听、任务控制和文件上传四大核心能力,并构建一个"上传下载实验室"Demo,在一个页面中完成下载全流程操作。

一、API 架构:任务对象模型

1.1 核心设计理念

@ohos.request 的设计核心是任务对象模式。调用 downloadFile()uploadFile() 不是直接开始传输,而是返回一个任务对象(DownloadTaskUploadTask)。开发者持有这个任务对象,可以:

  • 注册 on('progress') 回调监听实时进度
  • 调用 suspend() 暂停传输
  • 调用 restore() 恢复传输
  • 调用 delete() 取消并删除任务
  • 调用 getTaskInfo() 查询任务详情
import request from '@ohos.request';

// 1. 创建下载任务
const task = await request.downloadFile(context, {
  url: 'https://example.com/file.zip',
  filePath: '/data/storage/el2/base/file.zip'
});

// 2. 监听进度
task.on('progress', (receivedSize: number, totalSize: number) => {
  const pct = Math.round((receivedSize / totalSize) * 100);
  console.log('下载进度: ' + pct.toString() + '%');
});

// 3. 控制任务
await task.suspend();   // 暂停
await task.restore();    // 恢复
await task.delete();     // 取消

这种任务对象模型有三个优势:

  • 生命周期完整:创建 → 运行 → 暂停 → 恢复 → 完成/取消,每个状态都有对应的 API
  • 事件驱动on/off 模式注册和移除进度回调,无需 Polling
  • 资源可控:通过 suspend/restore 实现带宽管理,WiFi 切换蜂窝网络时自动暂停

1.2 downloadFile —— 创建下载任务

downloadFile(context: BaseContext, config: DownloadConfig): Promise<DownloadTask> 创建一个下载任务并立即开始下载。需要两个参数:

context:应用的 BaseContext 对象。在 ArkUI 组件中通过 getContext(this) 获取。这个参数用于系统服务绑定和沙箱路径解析。

configDownloadConfig 配置对象,包含以下字段:

字段 类型 必填 说明
url string 资源下载地址,https:// 开头,最长 2048 字符
filePath string 文件保存路径。不指定时系统自动选择默认下载目录
header Object HTTP 请求头,用于认证、UA 自定义等
enableMetered boolean 是否允许在计量网络(蜂窝数据)下下载
enableRoaming boolean 是否允许在漫游网络下下载
const ctx = getContext(this);
const config: request.DownloadConfig = {
  url: 'https://jsonplaceholder.typicode.com/posts/1',
  enableMetered: true,
  enableRoaming: true
};

request.downloadFile(ctx, config).then((task: request.DownloadTask) => {
  this.dlTask = task;
  // 注册进度回调
  task.on('progress', (received: number, total: number) => {
    this.dlDownloaded = this.formatSize(received);
    if (total > 0) {
      this.dlProgress = Math.round((received / total) * 100);
    }
  });
}).catch((e: Error) => {
  // 下载失败处理
});

关键设计细节:

  • filePath 可选——不指定路径时系统会将文件保存到默认下载目录,适合"下载后用其他应用打开"的场景
  • enableMetered 默认为 false,意味着在蜂窝网络下不会自动开始下载。对于小文件(如 JSON 响应),建议设为 true
  • 返回的 DownloadTask 对象立即可用,可以在 Promise resolve 之前就注册 on('progress') ——但最佳实践是 resolve 后再注册

1.3 DownloadTask —— 进度监听与生命周期

DownloadTask 是下载操作的核心对象,提供四个关键能力:

进度监听

task.on('progress', (receivedSize: number, totalSize: number) => void): void

回调参数:

  • receivedSize:已接收的字节数(number 类型)
  • totalSize:文件总大小(number 类型)。重要:totalSize 可能为 0,表示服务器未返回 Content-Length 响应头。在这种情况下,progress 回调仍然触发,但百分比无法计算。Demo 中对此做了防御性处理:
task.on('progress', (received: number, total: number) => {
  this.dlDownloaded = this.formatSize(received);
  if (total > 0) {
    const pct = Math.round((received / total) * 100);
    this.dlProgress = pct;
    this.dlProgressText = pct.toString() + '%';
    if (pct >= 100) {
      this.dlDownloading = false;
      task.off('progress');  // 下载完成后移除监听
    }
  } else {
    // 无法获取总大小,只显示已下载量
    this.dlProgressText = this.formatSize(received);
  }
});

任务控制

  • suspend(): Promise<boolean> — 暂停下载。返回 true 表示暂停成功
  • restore(): Promise<boolean> — 恢复已暂停的下载。返回 true 表示恢复成功
  • delete(): Promise<boolean> — 取消下载并删除任务。返回 true 表示删除成功

这三个方法全部返回 Promise,不建议使用它们的同步变体(文档中可能有 deprecated 标记)。

回调清理

  • off('progress', callback?) — 移除进度回调。传入具体 callback 移除指定监听器,不传则移除所有

最佳实践是在下载完成后(100%)或取消下载时调用 off('progress'),防止内存泄漏。在组件销毁(aboutToDisappear)时也要做安全保障:

aboutToDisappear(): void {
  if (this.dlTask !== null) {
    try {
      this.dlTask.off('progress');
    } catch (e) {
      // 任务可能已结束,忽略异常
    }
  }
}

二、文件上传

2.1 uploadFile —— 创建上传任务

uploadFile(context: BaseContext, config: UploadConfig): Promise<UploadTask> 创建一个文件上传任务。

UploadConfig 配置对象:

字段 类型 必填 说明
url string 上传目标地址
filePath string 要上传的本地文件路径
header Object HTTP 请求头

与下载不同,上传的 filePath必填项——必须指向本地实际存在的文件。UploadTask 同样支持 on('progress', callback)suspend()restore()delete(),API 与 DownloadTask 完全对称。

const upConfig: request.UploadConfig = {
  url: 'https://httpbin.org/post',
  filePath: '/data/storage/el2/base/haps/entry/files/photo.jpg'
};

request.uploadFile(ctx, upConfig).then((task: request.UploadTask) => {
  task.on('progress', (uploaded: number, total: number) => {
    console.log('已上传: ' + uploaded.toString() + ' / ' + total.toString());
  });
});

在这里插入图片描述
在这里插入图片描述

三、实战 Demo:上传下载实验室

3.1 页面设计

"上传下载实验室"页面分为四个功能区域:

  1. 文件下载面板:URL 输入框 + 下载按钮。下方三个预设快捷按钮(favicon.ico / JSON / HTML),点击后自动填入 URL 并开始下载。

  2. 进度面板:大字显示下载百分比和"已下载 / 总大小"。Progress 线性进度条(indigo 色 #4F46E5)实时反映下载进度。

  3. 任务控制区:三个按钮——“暂停”(黄色,仅在下载中可用)、“继续”(绿色,仅在暂停后可用)、“取消”(红色,仅在任务存在时可用)。每个按钮通过 enabled 属性控制可用状态。

  4. 操作日志:记录任务创建、进度变化、暂停/恢复/取消、错误等事件,按类别着色。

3.2 核心实现

状态模型设计:

@State dlUrl: string = 'https://www.example.com/favicon.ico';
@State dlProgress: number = 0;
@State dlProgressText: string = '0%';
@State dlDownloaded: string = '0 B';
@State dlTotal: string = '--';
@State dlDownloading: boolean = false;
@State dlTaskExists: boolean = false;
@State dlPaused: boolean = false;
private dlTask: request.DownloadTask | null = null;

状态设计要点:

  • dlDownloadingdlTaskExistsdlPaused 三个布尔状态精确描述当前任务的运行状态,驱动按钮的 enabled 属性
  • dlTaskprivate 而非 @State 声明——DownloadTask 对象不是 UI 状态,不需要触发重渲染
  • dlProgress 是数字(0-100),驱动 Progress 组件;dlProgressText 是显示用字符串(“45%” 或 “2.5 KB”)

文件大小格式化:

private formatSize(bytes: number): string {
  if (bytes < 1024) return bytes.toString() + ' B';
  if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
  return (bytes / (1024 * 1024)).toFixed(2) + ' MB';
}

进度回调中同时展示格式化后的大小(“1.5 KB”)和原始百分比(“45%”),让用户对下载进度有定性和定量的双重感知。

暂停/恢复/取消的三态联动:

// 按钮 enabled 条件
// "暂停": dlDownloading && !dlPaused → 正在下载且未暂停
// "继续": dlPaused → 已暂停状态
// "取消": dlTaskExists → 任务对象存在

// 暂停
private pauseDownload(): void {
  this.dlTask?.suspend().then(() => {
    this.dlPaused = true;
    this.dlDownloading = false;
  });
}

// 恢复
private resumeDownload(): void {
  this.dlTask?.restore().then(() => {
    this.dlPaused = false;
    this.dlDownloading = true;
  });
}

// 取消
private cancelDownload(): void {
  this.dlTask?.off('progress');  // 先移除监听
  this.dlTask?.delete().then(() => {
    this.dlTask = null;
    this.dlDownloading = false;
    this.dlTaskExists = false;
    this.dlPaused = false;
    this.dlProgress = 0;
    this.dlProgressText = '0%';
  });
}

取消操作的关键在于先 off('progress')delete()——如果顺序反了,progress 回调可能在 delete 过程中触发,导致状态异常。

3.3 交互方式

Demo 提供三个核心交互点:

  1. 输入 URL 下载:在 TextInput 中输入下载地址(或点击预设快捷按钮),点击"下载"按钮开始下载。下载过程中按钮变为灰色"下载中"并禁用,防止重复创建任务。

  2. 实时进度追踪:Progress 组件配合百分比文字和"已下载/总大小"实时更新。对于有 Content-Length 的响应,进度条从 0% 平滑增长到 100%;对于无 Content-Length 的响应,显示已下载的字节数。

  3. 任务三态控制:下载进行中可以"暂停"(变为暂停状态,按钮变为可"继续"),暂停后可以"继续"恢复下载或"取消"删除任务。取消后所有状态重置为初始值。

四、实际应用场景

4.1 更新包下载器

async function downloadUpdate(url: string, onProgress: (pct: number) => void): Promise<string> {
  const task = await request.downloadFile(getContext(), {
    url: url,
    enableMetered: true,
    enableRoaming: false
  });

  return new Promise((resolve, reject) => {
    task.on('progress', (received, total) => {
      if (total > 0) {
        onProgress(Math.round((received / total) * 100));
      }
      if (received === total && total > 0) {
        task.off('progress');
        resolve('download complete');
      }
    });
  });
}

4.2 WiFi 切换自动暂停

// 伪代码:配合 @ohos.net.connection 检测网络变化
function onNetworkChanged(isWifi: boolean): void {
  if (isWifi) {
    task?.restore();  // WiFi 环境恢复下载
  } else {
    task?.suspend();  // 蜂窝网络暂停大文件下载
  }
}

五、总结

@ohos.request 是 HarmonyOS NEXT 中文件上传下载的统一模块。通过本文的学习,你应该已经掌握:

  1. 任务对象模型downloadFile / uploadFile 返回 DownloadTask / UploadTask,Promise 创建 + on/off 事件监听,生命周期完整
  2. 进度监听task.on('progress', (receivedSize, totalSize) => void),totalSize 可能为 0 需要防御性处理,下载完成或取消时必须 off('progress') 清理回调
  3. 任务控制三态suspend() 暂停、restore() 恢复、delete() 取消——三者驱动按钮联动状态机
  4. DownloadConfig 配置:url(必填)、filePath(可选)、header、enableMetered、enableRoaming——支持认证请求头、计量网络控制和漫游限制
  5. context 获取:在 ArkUI 组件中通过 getContext(this) 获取 BaseContext 传给 downloadFile/uploadFile

@ohos.request 的最佳使用模式可以总结为:

创建任务 → 注册 progress 回调 → 根据 totalSize 计算百分比 → 100% 时 off(‘progress’) 清理 → 异常时显示错误。suspend/restore 实现带宽管理,delete 处理用户取消。context 通过 getContext(this) 获取。

文件传输是移动应用的核心网络能力之一。虽然 HTTP 也可以实现文件下载,但 @ohos.request 提供的系统级下载代理拥有后台传输、网络切换自动处理、通知栏进度显示等企业级特性——这些是 @ohos.net.http 无法替代的。在 HarmonyOS 网络通信体系中,@ohos.request 定位于"大文件传输 + 任务管理",与 @ohos.net.http(REST API 请求)和 @ohos.net.connection(网络状态检测)形成完整的三级网络能力栈。

@ohos.request 属于 @kit.BasicServicesKit,是系统级文件传输代理。它的 API 设计遵循"Promise 创建 + 事件驱动"模式——一次 downloadFile() 调用返回一个长生命周期任务对象,开发者持有该对象即可完成从创建到销毁的全部控制。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐