HarmonyOS 5.0 应用开发——RCP 框架实现断点续传
作者:高心星
- 2024-10-31 江苏
本文字数:1978 字
阅读完需:约 6 分钟
【高心星出品】
RCP 框架实现断点续传
RCP 框架有提供 downloadToStream 方法来实现下载文件,并将文件字节转化成流。结合设置请求头的 range 属性就可以实现断点续传的功能。
断点续传原理
如果要下载的网络资源比较大,我们可以将网络资源字节分割成多份,通过设置请求头的 range 字段来控制下载哪一份资源,然后将下载后的资源通过流写入单个文件就可以实现断点续传下载文件。
表示头500个字节:Range: bytes=0-499
表示第二个500字节:Range: bytes=500-999
表示最后500个字节:Range: bytes=-500
表示500字节以后的范围:Range: bytes=500-
第一个和最后一个字节:Range: bytes=0-0,-1
同时指定几个范围:Range: bytes=500-600,601-999
复制代码
除此之外还需要获得网络资源的总大小,这里可以通过 RCP 框架中 Session 对象的 head 方法去读取网络资源的信息,主要读取 content-length 字段,该字段返回的是网络资源的字节个数。
let getres = await this.session.head(url) //只获取网络资源应答头
this.filetotal = Number.parseInt(getres.headers?.['content-length'] as string) //获取应答头的资源长度
复制代码
代码:
import { rcp } from '@kit.RemoteCommunicationKit';
import { fileIo } from '@kit.CoreFileKit';
import { promptAction } from '@kit.ArkUI';
@Entry
@Component
struct Index {
// 请求头中返回资源字节的开始位置和结束位置
@State range: string = ''
// 当前已经下载的字节个数
@State count: number = 0
// 要下载的文件字节总个数
@State filetotal: number = 0
// 进度条显示进度值
@State value: number = 0
// 是否为第一次点击按钮下载
@State isstart: boolean = true
// 下载文件的会话对象
private session: rcp.Session | null = null
start = async (event: ClickEvent) => { //开始按钮
let url = 'https://dldir1.qq.com/qqfile/qq/QQNT/Windows/QQ_9.9.15_240927_x64_01.exe'
// 请求头中加入资源截取位置
let sessionconfig: rcp.SessionConfiguration = {
headers: {
range: this.range
}
}
this.session = rcp.createSession(sessionconfig)
//创建文件
let file =
fileIo.openSync(getContext(this).filesDir + '/QQ.exe', fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE|fileIo.OpenMode.APPEND)
let downloadstream: rcp.DownloadToStream = {
kind: 'stream',
stream: {
writeSync: (buffer: ArrayBuffer) => { //每次获取网络资源然后写入文件
let len = fileIo.writeSync(file.fd, buffer) //写入文件
this.count += len //更新字节总个数
this.value = this.count*100 / this.filetotal //更新进度值
return len
}
}
}
if(this.isstart) { //第一次点击开始按钮获取网络资源总大小
let getres = await this.session.head(url) //只获取网络资源应答头
this.filetotal = Number.parseInt(getres.headers?.['content-length'] as string) //获取应答头的资源长度
}
this.session.downloadToStream(url, downloadstream)
.then((res) => { //下载结束之后
this.value = 100
promptAction.showToast({message:'下载完毕'})
})
.catch((e: Error) => { //如果强制关闭session会调用异常处理
this.range = `bytes=${this.count}-${this.filetotal}` //更新rang值 在这里能确保this.count是准确已经下载文件资源的字节个数
console.error('gxxt ', e.message)
})
.finally(() => {
this.session?.close()
})
}
stop = (event: ClickEvent) => {//暂停按钮
this.isstart = false //将第一次点击设置为false
this.session?.close() //强制关闭会话对象,后面会引起捕获异常
}
build() {
Column() {
Progress({ value: this.value, total: 100, type: ProgressType.Capsule }).width('100%').height(20).color(Color.Red)
Row() {
Button('开始下载')
.width('45%')
.onClick(this.start)
Button('暂停下载')
.width('45%')
.onClick(this.stop)
}.width('100%').justifyContent(FlexAlign.Center).margin({ top: 20 })
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
aboutToAppear(): void {
// 如果要保存文件位置已经有文件了,就删除
if(fileIo.accessSync(getContext(this).filesDir + '/QQ.exe'))
{
fileIo.unlinkSync(getContext(this).filesDir + '/QQ.exe')
}
}
}
复制代码
划线
评论
复制
发布于: 刚刚阅读数: 5
高心星
关注
天将降大任于斯人也,必先苦其心志。 2024-10-17 加入
华为开发者专家(HDE)。 10年教学经验,兼任多家科技公司技术顾问。先后从事JavaEE项目开发、Python爬虫、HarmonyOS移动应用开发等课程的教学工作。参与开发《鸿蒙应用开发基础》和《鸿蒙项目实战》等课程。
评论