两种方式实现多线程下载文件
一. worker 线程
Index.ets 代码
import { MessageEvents, worker } from '@kit.ArkTS';
//创建一个worker子线程
const download = new worker.ThreadWorker('entry/ets/workers/downloadWorker.ets')
@Entry
@Component
struct Index {
@State message: string = 'Hello World';
@State pro: number = 0
//接收子线程传递过来的数据
aboutToAppear(): void {
download.onmessage = (e:MessageEvents) => {
this.pro = e.data.pro
}
}
build() {
Column() {
Button('下载文件')
.onClick((event: ClickEvent) => {
//多线程下载文件
//主线程更新
//主线程给子线程发消息,将dir路径传递给子线程
download.postMessage({dir:getContext().filesDir})
})
Stack(){
Progress({value:this.pro,total:100,type:ProgressType.Capsule})
.width('80%')
.height(20)
.color(Color.Red)
.backgroundColor(Color.Gray)
Text(this.pro + '%')
.fontColor(Color.White)
.align(Alignment.Center)
}
.width('100%')
.margin({top:30})
}
.height('100%')
.width('100%')
}
}
通过worker模版创建一个worker子线程
/*
* 通过worker模版创建子线程
* */
import { ErrorEvent, MessageEvents, ThreadWorkerGlobalScope, worker } from '@kit.ArkTS';
import { download } from '../util/httputil';
const workerPort: ThreadWorkerGlobalScope = worker.workerPort;
/**
* Defines the event handler to be called when the worker thread receives a message sent by the host thread.
* The event handler is executed in the worker thread.
*
* @param e message data
*/
//子线程接收主线程消息
workerPort.onmessage = (e: MessageEvents) => {
let uri = ''
//子线程获取不到dir,需要从主线程传过来
//子线程执行下载操作
download(uri,e.data.dir,(progress:number)=>{
//子线程获取到progress后,通过postmessage 传给主线程
workerPort.postMessage({pro:progress})
})
}
/**
* Defines the event handler to be called when the worker receives a message that cannot be deserialized.
* The event handler is executed in the worker thread.
*
* @param e message data
*/
workerPort.onmessageerror = (e: MessageEvents) => {
}
/**
* Defines the event handler to be called when an exception occurs during worker execution.
* The event handler is executed in the worker thread.
*
* @param e error message
*/
workerPort.onerror = (e: ErrorEvent) => {
}
二. request.download (不支持断点续传)
另外创建一个page
import { request } from '@kit.BasicServicesKit';
import { promptAction } from '@kit.ArkUI';
@Entry
@Component
struct RequestPage {
@State message: string = 'Hello World';
@State pro: number = 0
config:request.DownloadConfig = {
url:'',
background:true
}
build() {
Column() {
Button('下载文件')
.onClick((event: ClickEvent) => {
//多线程下载文件
//主线程更新
request.downloadFile(getContext(),this.config).then((task:request.DownloadTask) => {
task.on("progress",(rs:number,ts:number) => {
this.pro = Math.ceil(rs*100/ts)
})
task.on("complete",()=>{
this.pro = 100
promptAction.showToast({message:'下载文件'})
})
})
})
Stack(){
Progress({value:this.pro,total:100,type:ProgressType.Capsule})
.width('80%')
.height(20)
.color(Color.Red)
.backgroundColor(Color.Gray)
Text(this.pro + '%')
.fontColor(Color.White)
.align(Alignment.Center)
}
.width('100%')
.margin({top:30})
}
.height('100%')
.width('100%')
}
}
三,request.agent.download (支持断点续传)
import { request } from '@kit.BasicServicesKit';
import { promptAction } from '@kit.ArkUI';
@Entry
@Component
struct RequestPage {
@State message: string = 'Hello World';
@State pro: number = 0
config:request.agent.Config = {
url:'',
action:request.agent.Action.DOWNLOAD,
overwrite:true,
gauge:true
}
@State taskId:string = ''
async onPageShow(): Promise<void> {
let task = await request.agent.create(getContext(), this.config)
task.on("progress",(progress:request.agent.Progress) =>{
this.pro = Math.ceil(progress.processed * 100 / progress.sizes[0])
})
task.on("completed",() => {
this.pro = 100
promptAction.showToast({message:'文件下载完成'})
})
this.taskId = task.tid
}
build() {
Column() {
Button('下载文件')
.onClick((event: ClickEvent) => {
//多线程下载文件
//主线程更新
//支持断点续传
request.agent.getTask(getContext(),this.taskId).then((task) => {
task.start()
})
})
.alignSelf(ItemAlign.Start)
Button('暂停')
.onClick((event: ClickEvent) => {
request.agent.getTask(getContext(),this.taskId).then((task) => {
task.pause()
})
})
.alignSelf(ItemAlign.Start)
Button('继续')
.onClick((event: ClickEvent) => {
request.agent.getTask(getContext(),this.taskId).then((task) => {
task.resume()
})
})
.alignSelf(ItemAlign.Start)
Stack(){
Progress({value:this.pro,total:100,type:ProgressType.Capsule})
.width('80%')
.height(20)
.color(Color.Red)
.backgroundColor(Color.Gray)
Text(this.pro + '%')
.fontColor(Color.White)
.align(Alignment.Center)
}
.width('100%')
.margin({top:30})
}
.height('100%')
.width('100%')
}
}