鸿蒙新特性:@ohos.request 上传下载实验室实战 —— 文件传输、进度监听与任务管理
引言
文件上传下载是移动应用中最常见的网络操作之一——从更新包的静默下载到头像图片的上传,从离线内容包的获取到日志文件的回传。HarmonyOS NEXT 通过 @ohos.request 模块将上传下载能力统一封装为任务对象,提供完整的进度监听、暂停恢复和取消删除等生命周期管理。
@ohos.request 属于 @kit.BasicServicesKit,是系统级文件传输代理(File Transfer Agent)的统一入口。与 Android 的 DownloadManager + HttpURLConnection(分散在两个 API 中)和 iOS 的 URLSession(后台会话配置复杂)不同,鸿蒙将上传和下载整合到一个模块中,通过 DownloadTask 和 UploadTask 两个任务对象提供一致的 Promise + on/off 事件回调模型。
本文将深入讲解 @ohos.request 的文件下载、进度监听、任务控制和文件上传四大核心能力,并构建一个"上传下载实验室"Demo,在一个页面中完成下载全流程操作。
一、API 架构:任务对象模型
1.1 核心设计理念
@ohos.request 的设计核心是任务对象模式。调用 downloadFile() 或 uploadFile() 不是直接开始传输,而是返回一个任务对象(DownloadTask 或 UploadTask)。开发者持有这个任务对象,可以:
- 注册
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) 获取。这个参数用于系统服务绑定和沙箱路径解析。
config:DownloadConfig 配置对象,包含以下字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| 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 页面设计
"上传下载实验室"页面分为四个功能区域:
-
文件下载面板:URL 输入框 + 下载按钮。下方三个预设快捷按钮(favicon.ico / JSON / HTML),点击后自动填入 URL 并开始下载。
-
进度面板:大字显示下载百分比和"已下载 / 总大小"。Progress 线性进度条(indigo 色 #4F46E5)实时反映下载进度。
-
任务控制区:三个按钮——“暂停”(黄色,仅在下载中可用)、“继续”(绿色,仅在暂停后可用)、“取消”(红色,仅在任务存在时可用)。每个按钮通过
enabled属性控制可用状态。 -
操作日志:记录任务创建、进度变化、暂停/恢复/取消、错误等事件,按类别着色。
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;
状态设计要点:
dlDownloading、dlTaskExists、dlPaused三个布尔状态精确描述当前任务的运行状态,驱动按钮的enabled属性dlTask用private而非@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 提供三个核心交互点:
-
输入 URL 下载:在 TextInput 中输入下载地址(或点击预设快捷按钮),点击"下载"按钮开始下载。下载过程中按钮变为灰色"下载中"并禁用,防止重复创建任务。
-
实时进度追踪:Progress 组件配合百分比文字和"已下载/总大小"实时更新。对于有 Content-Length 的响应,进度条从 0% 平滑增长到 100%;对于无 Content-Length 的响应,显示已下载的字节数。
-
任务三态控制:下载进行中可以"暂停"(变为暂停状态,按钮变为可"继续"),暂停后可以"继续"恢复下载或"取消"删除任务。取消后所有状态重置为初始值。
四、实际应用场景
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 中文件上传下载的统一模块。通过本文的学习,你应该已经掌握:
- 任务对象模型:
downloadFile/uploadFile返回DownloadTask/UploadTask,Promise 创建 + on/off 事件监听,生命周期完整 - 进度监听:
task.on('progress', (receivedSize, totalSize) => void),totalSize 可能为 0 需要防御性处理,下载完成或取消时必须off('progress')清理回调 - 任务控制三态:
suspend()暂停、restore()恢复、delete()取消——三者驱动按钮联动状态机 - DownloadConfig 配置:url(必填)、filePath(可选)、header、enableMetered、enableRoaming——支持认证请求头、计量网络控制和漫游限制
- 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() 调用返回一个长生命周期任务对象,开发者持有该对象即可完成从创建到销毁的全部控制。
更多推荐


所有评论(0)