#跟着若城学鸿蒙# web篇-主动下载及恢复未完成的任务
·
前言
上篇文章中我们完成了文件下载功能,但有时候并不是通过点击链接被动响应下载任务,也有可能是点击按钮后,直接进行下载。这一篇文章中我们来看下如何主动发起一个下载任务
步骤
同样的,我们依然需要设置下载代理webview.WebDownloadDelegate,并且在其各种回调方法中处理业务逻辑。
downloadDelegate: webview.WebDownloadDelegate = new webview.WebDownloadDelegate();
aboutToAppear() {
this.initDownloadDelegate()
}
initDownloadDelegate(){
this.downloadDelegate.onBeforeDownload((webDownloadItem: webview.WebDownloadItem) => {
console.log("will start a download.");
// 传入一个下载路径,并开始下载。
// 如果传入一个不存在的路径,则会下载到默认/data/storage/el2/base/cache/web/目录。
let dir =getContext().cacheDir +"/web/" + webDownloadItem.getSuggestedFileName()
console.error("下载路径",dir)
webDownloadItem.start(dir);
})
this.downloadDelegate.onDownloadUpdated((webDownloadItem: webview.WebDownloadItem) => {
// 下载任务的唯一标识。
console.log("onDownloadUpdated 唯一标识 guid: " + webDownloadItem.getGuid());
// 下载的进度。
console.log("onDownloadUpdated 下载进度百分比: " + webDownloadItem.getPercentComplete());
// 当前的下载速度。
console.log("onDownloadUpdated 下载速度 : " + webDownloadItem.getCurrentSpeed())
})
this.downloadDelegate.onDownloadFailed((webDownloadItem: webview.WebDownloadItem) => {
console.log("onDownloadFailed 唯一标识 guid: " + webDownloadItem.getGuid());
// 下载任务失败的错误码。
console.log("onDownloadFailed last error code: " + webDownloadItem.getLastErrorCode());
})
this.downloadDelegate.onDownloadFinish((webDownloadItem: webview.WebDownloadItem) => {
console.log("onDownloadFinish guid: " + webDownloadItem.getGuid());
})
}
下载
这里下载的时候可能是前端通过调用native方法告知鸿蒙侧需要进行下载,或者直接是点击鸿蒙原生页面的按钮进行下载。
当触发该事件时,我们直接调用this.controller.startDownload('下载地址‘); 就可以了
恢复上次未完成的任务
想要恢复下载,我们需要在下载失败的时候保存下载的相关信息,需要调整一下之前下载代理相关代码
this.delegate.onBeforeDownload((webDownloadItem: webview.WebDownloadItem) => {
console.log("will start a download.");
// 传入一个下载路径,并开始下载。
webDownloadItem.start("/data/storage/el2/base/cache/web/" + webDownloadItem.getSuggestedFileName());
})
this.delegate.onDownloadUpdated((webDownloadItem: webview.WebDownloadItem) => {
console.log("download update percent complete: " + webDownloadItem.getPercentComplete());
this.download = webDownloadItem;
})
this.delegate.onDownloadFailed((webDownloadItem: webview.WebDownloadItem) => {
console.log("download failed guid: " + webDownloadItem.getGuid());
// 序列化失败的下载任务到一个字节数组。
this.failedData = webDownloadItem.serialize();
})
this.delegate.onDownloadFinish((webDownloadItem: webview.WebDownloadItem) => {
console.log("download finish guid: " + webDownloadItem.getGuid());
})
this.controller.setDownloadDelegate(this.delegate);
然后我们来模拟一下
import { webview } from '@kit.ArkWeb';
import { BusinessError } from '@kit.BasicServicesKit';
import { downloadUtil, fileName, filePath } from './downloadUtil'; // downloadUtil.ets 见下文
@Entry
@Component
struct WebComponent {
controller: webview.WebviewController = new webview.WebviewController();
delegate: webview.WebDownloadDelegate = new webview.WebDownloadDelegate();
download: webview.WebDownloadItem = new webview.WebDownloadItem();
// 用于记录失败的下载任务。
failedData: Uint8Array = new Uint8Array();
aboutToAppear(): void {
downloadUtil.init(this.getUIContext());
}
Button('record')
.onClick(() => {
try {
// 保存当前下载数据到持久化文档中。
downloadUtil.saveDownloadInfo(downloadUtil.uint8ArrayToStr(this.download.serialize()));
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
});
Button('recovery')
.onClick(() => {
try {
// 当前默认持久化文件存在,用户根据实际情况增加判断。
let webDownloadItem = webview.WebDownloadItem.deserialize(downloadUtil.strToUint8Array(downloadUtil.readFileSync(filePath, fileName)));
webview.WebDownloadManager.resumeDownload(webDownloadItem);
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
});
}
工具类相关代码
// downloadUtil.ets
import { util } from '@kit.ArkTS';
import fileStream from '@ohos.file.fs';
const helper = new util.Base64Helper();
export const filePath = getContext().filesDir;
export const fileName = 'demoFile.txt';
export namespace downloadUtil {
export function uint8ArrayToStr(uint8Array: Uint8Array): string {
return helper.encodeToStringSync(uint8Array);
}
export function strToUint8Array(str: string): Uint8Array {
return helper.decodeSync(str);
}
export function saveDownloadInfo(downloadInfo: string): void {
if (!fileExists(filePath)) {
mkDirectorySync(filePath);
}
writeToFileSync(filePath, fileName, downloadInfo);
}
export function fileExists(filePath: string): boolean {
try {
return fileStream.accessSync(filePath);
} catch (error) {
return false;
}
}
export function mkDirectorySync(directoryPath: string, recursion?: boolean): void {
try {
fileStream.mkdirSync(directoryPath, recursion ?? false);
} catch (error) {
console.error(`mk dir error. err message: ${error.message}, err code: ${error.code}`);
}
}
export function writeToFileSync(dir: string, fileName: string, msg: string): void {
let file = fileStream.openSync(dir + '/' + fileName, fileStream.OpenMode.WRITE_ONLY | fileStream.OpenMode.CREATE);
fileStream.writeSync(file.fd, msg);
}
export function readFileSync(dir: string, fileName: string): string {
return fileStream.readTextSync(dir + '/' + fileName);
}
}
这样我们就完成了任务的恢复。
其实这种场景不是常见,如果需要下载大文件,一般来讲会通过鸿蒙原生相关方法来下载,而不是使用web的下载功能。
更多推荐



所有评论(0)