欢迎光临
我们一直在努力

HarmonyOS ArkWeb 系列之组件发起文件下载:WebDownloadDelegate 教程

文章目录

      • 大白话解释下载流程
      • 流程图
      • 最基础的下载实现
      • 加上进度显示
      • WebDownloadItem 常用方法速查
      • 几个常见坑
      • 写在最后

在 App 里内嵌一个 Web 页面,用户点击页面上的下载链接,文件该怎么存?系统有默认行为,但路径不可控、进度没有回调,基本不够用。WebDownloadDelegate 让你完全接管下载流程。

大白话解释下载流程

想象一个快递员帮你取件:

  • WebDownloadDelegate:就是你雇的快递员,你告诉他各种情况下怎么处理
  • onBeforeDownload:快递员出发前问你"要存哪儿?",你告诉他路径后他才开始取
  • onDownloadUpdated:快递员途中给你发进度消息
  • onDownloadFinish:快递员把包裹送到了,通知你完成
  • onDownloadFailed:路上出了问题,告诉你失败了

流程图

最基础的下载实现

import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct WebDownloadBasicDemo {
controller: webview.WebviewController = new webview.WebviewController();
// 创建下载委托对象
delegate: webview.WebDownloadDelegate = new webview.WebDownloadDelegate();
@State downloadStatus: string = '等待下载';

build() {
Column({ space: 12 }) {
Text(this.downloadStatus)
.fontSize(16)
.padding(8)

Button('注册下载委托')
.onClick(() => {
try {
// 1. 下载开始前:指定保存路径
this.delegate.onBeforeDownload((webDownloadItem: webview.WebDownloadItem) => {
console.info('即将开始下载:', webDownloadItem.getSuggestedFileName());
// 指定下载路径(文件名用 getSuggestedFileName 获取)
// 路径不存在时会自动下载到默认目录
webDownloadItem.start(
'/data/storage/el2/base/cache/web/' +
webDownloadItem.getSuggestedFileName()
);
});

// 2. 下载进度更新
this.delegate.onDownloadUpdated((webDownloadItem: webview.WebDownloadItem) => {
console.info('下载中,任务ID:', webDownloadItem.getGuid());
});

// 3. 下载失败
this.delegate.onDownloadFailed((webDownloadItem: webview.WebDownloadItem) => {
console.error('下载失败,任务ID:', webDownloadItem.getGuid());
this.downloadStatus = '下载失败';
});

// 4. 下载完成
this.delegate.onDownloadFinish((webDownloadItem: webview.WebDownloadItem) => {
console.info('下载完成,任务ID:', webDownloadItem.getGuid());
this.downloadStatus = '下载完成 ✓';
});

// 5. 把委托绑定到 controller
this.controller.setDownloadDelegate(this.delegate);
this.downloadStatus = '委托已注册,等待下载触发';
} catch (error) {
console.error(
`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`
);
}
})

Button('手动触发下载')
.onClick(() => {
try {
// 编程方式发起下载(而非点击网页链接)
this.controller.startDownload('https://img1.baidu.com/it/u=2172818577,3783888802&fm=253&app=138&f=JPEG?w=800&h=1422');
this.downloadStatus = '下载进行中…';
} catch (error) {
console.error(
`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`
);
}
})

Web({ src: 'https://www.baidu.com', controller: this.controller })
.width('100%')
.layoutWeight(1)
}
.width('100%')
.height('100%')
.padding(16)
}
}

加上进度显示

onDownloadUpdated 里可以拿到更多信息:

import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';

@Entry
@Component
struct WebDownloadProgressDemo {
controller: webview.WebviewController = new webview.WebviewController();
delegate: webview.WebDownloadDelegate = new webview.WebDownloadDelegate();

@State progress: number = 0; // 下载进度 0~100
@State speed: number = 0; // 当前速度(字节/秒)
@State statusText: string = '等待';

build() {
Column({ space: 12 }) {
// 进度条
Progress({ value: this.progress, total: 100, type: ProgressType.Linear })
.width('100%')

Text(`${this.statusText} ${this.progress}% 速度:${(this.speed / 1024).toFixed(1)} KB/s`)
.fontSize(14)

Button('开始下载')
.onClick(() => {
try {
this.delegate.onBeforeDownload((item: webview.WebDownloadItem) => {
item.start('/data/storage/el2/base/cache/web/' + item.getSuggestedFileName());
this.statusText = '下载中';
});

this.delegate.onDownloadUpdated((item: webview.WebDownloadItem) => {
// 获取进度(0~100,-1 表示不确定)
this.progress = item.getPercentComplete() > 0 ? item.getPercentComplete() : 0;
// 获取当前下载速度(字节/秒)
this.speed = item.getCurrentSpeed();
});

this.delegate.onDownloadFailed((item: webview.WebDownloadItem) => {
this.statusText = `失败(错误码:${item.getLastErrorCode()}`;
});

this.delegate.onDownloadFinish((item: webview.WebDownloadItem) => {
this.progress = 100;
this.statusText = '完成';
});

this.controller.setDownloadDelegate(this.delegate);
this.controller.startDownload('https://img1.baidu.com/it/u=2172818577,3783888802&fm=253&app=138&f=JPEG?w=800&h=1422');
} catch (error) {
console.error(`下载错误: ${(error as BusinessError).message}`);
}
})

Web({ src: 'https://www.baidu.com', controller: this.controller })
.width('100%')
.layoutWeight(1)
}
.width('100%')
.height('100%')
.padding(16)
}
}

WebDownloadItem 常用方法速查

方法说明
getGuid() 下载任务唯一ID
getSuggestedFileName() 服务端建议的文件名
getPercentComplete() 下载进度(0~100,-1=不确定)
getCurrentSpeed() 当前下载速度(字节/秒)
getLastErrorCode() 下载失败的错误码
start(path) 在 onBeforeDownload 中调用,指定保存路径并开始下载
cancel() 取消下载
pause() 暂停下载
resume() 恢复下载
serialize() 序列化任务信息(用于跨进程恢复)

几个常见坑

坑1:忘记调 setDownloadDelegate

创建好 delegate,设置好回调,但如果不调 controller.setDownloadDelegate(this.delegate) 绑定到 controller,所有回调都不会触发。

坑2:在 onBeforeDownload 里不调 start()

如果你在 onBeforeDownload 里什么都不做(不调 start()),下载会超时失败。必须在这里告诉系统文件存到哪里。

坑3:下载路径需要 App 有写权限

/data/storage/el2/base/cache/web/ 是 App 沙盒目录,有权限。如果你想存到下载目录(/data/storage/el2/base/files/Download/)也可以,同样是沙盒范围内有权限的路径。

写在最后

WebDownloadDelegate 的设计挺直觉的,四个回调覆盖下载的全生命周期。最重要的是别忘了在 onBeforeDownload 里调 start(path),这是下载真正开始的触发器。下一篇会讲更复杂的断点续传,把下载做得更健壮。

赞(0)
未经允许不得转载:171主机测评 » HarmonyOS ArkWeb 系列之组件发起文件下载:WebDownloadDelegate 教程
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址