龙空技术网

鸿蒙上实现一个“下载进度条”

51CTO 56855

前言:

眼前朋友们对“js下载进度”大概比较关心,小伙伴们都需要剖析一些“js下载进度”的相关内容。那么小编在网上网罗了一些有关“js下载进度””的相关内容,希望我们能喜欢,兄弟们一起来了解一下吧!

作者:FFH_PETSJ

本文基于 ArkUI request API 实现下载进度获取及显示。

在鸿蒙应用开发中,我们常用两种方式来实现文件的下载:

使用系统能力:

SystemCapability.Communication.NetStack(@ohos.http)

使用系统能力:

SystemCapability.MiscServices.Download(@ohos.request)

区别如下:前者下载过程信息不可见,后者会在手机状态栏显示下载会话,并且可被应用监听;前者请求下载后不会对文件作进一步处理,后者会直接保存到指定目录。

使用场景如下:下载大体积文件时监听进度文件下载直接到本地保存

文档传送门:

下面,我们基于 ArkUI-ts 来实现一个下载进度条的显示,以 API 8、FA 模型为例。

API 9 接口稍有改动,若使用 API 9、Stage 模型,请参考官方文档OpenHarmony,但基本的代码思路是不变的。

变动:相比于 API 8 的 FA 模型,加入了 Context 的传参;增加了uploadFile()、downloadFile() 方法,保留 upload()、donwload() 方法。

实现流程

首先配置网络权限(config.json–>module 下添加):

"reqPermissions": [   {      "name": "ohos.permission.INTERNET"   }],

支持 http(config.json 下添加):

"deviceConfig": {    "default": {        "network": {            "cleartextTraffic": true        }    }},
①下载配置

导入系统接口:

import request from '@ohos.request'

DownloadConfig

常用的字段配置:

其它的字段配置:

示例 1:例如通过图片 url 下载保存到本地的 internal://cache 的 myDownload/test.png 路径,文件名为 test.png。

let downloadConfig: request.DownloadConfig = {    url: downloadUrl,    filePath: 'myDownload/test.png',    description: 'Download Test',}

internal://cache 是应用沙箱路径,获取方法:

import featureAbility from "@ohos.ability.featureAbility"let cacheSandPath = featureAbility.getConext().getCacheDoir()

目前 js api 只支持在 filePath 配置在 internal://cache 下(默认)。

我们有两种方式可以访问到下载的文件:一是内部储存目录 storage 路径 file 目录;二是只允许本应用访问的沙箱路径 cache 目录。

这个知识点在后面的 Image 显示会用到。

②创建下载任务

let downloadTask    request.download(downloadConfig, (err, data) => {      if (err) {        console.info('xxx--- Failed to request the download. Cause: ' + JSON.stringify(err))        return      }      downloadTask = data})
③监听下载事件

request.DownloadTask:

request.DownloadInfo:

想要实现下载进度的监听,从上面的方法我们可以找到对应的方法 on(“progress”)。

示例 3-1

downloadTask.on('progress', (receiveSize: number, totalSize: number) => {    this.curProgressValue = (receiveSize / totalSize) * 100    this.curTaskDownloadedSize = receiveSize    this.curTaskTotalSize = totalSize})

经过测试发现,直接使用 on(‘progress’) 不一定能监听到实时下载大小和总大小,返回值 receivedSize 和 totalSize 可能为 0。

因此当 on(“progress”) 的返回值为 0 时,我们可以用另外一个方法 query() 来查询实时下载中的进度信息,或是在 query() 中使用 on(‘progress’)。

示例 3-2

进度的监听:

let downloadInfoFilePath:string = ''downloadTask.query().then((downloadInfo:request.DownloadInfo) => {    downloadInfoFilePath = downloadInfo.filePath                // 此处返回的路径不同于应用沙箱路径    this.downloadTask = data    this.downloadTask.on('progress', (receiveSize: number, totalSize: number) => {        this.curProgressValue = (receiveSize / totalSize) * 100 // 进度条Progress属性值        this.curTaskDownloadedSize = receiveSize                 // 实时下载大小        this.curTaskTotalSize = totalSize                        // 总大小    })    /*  或使用query返回的downloadInfo获取下载进度信息        this.curTaskDownloadedSize = downloadInfo.downloadedBytes        this.curTaskTotalSize = downloadInfo.downloadTotalBytes        this.curProgressValue = (this.curTaskDownloadedSize / this.curTaskTotalSize) * 100    */    console.info('xxx--- downloadTask queried info:' + JSON.stringify(downloadInfo))}).catch((err) => {    console.info('xxx--- Failed to query the downloadTask:' + JSON.stringify(err))})

示例 3-3

complete、fail、pause 事件的监听:

downloadTask.query().then((downloadInfo:request.DownloadInfo) => {    ......    var self = this    var clearListeners = function () {        self.downloadTask.off('progress')        self.downloadTask.off('fail')        self.downloadTask.off('remove')        self.downloadTask.off('complete')    }    this.downloadTask.on('fail', (err) => {        clearListeners()        this.curProgressValue = 0    })    this.downloadTask.on('remove', () => {        clearListeners()        this.curProgressValue = 0    })    this.downloadTask.on('complete', () => {        clearListeners()        this.curProgressValue = 100        // downloadInfoList:string[] 保存下载历史的路径        this.downloadInfoList.push(downloadInfoFilePath)    })})

④下载结果反馈

定义一个 Progress 组件来显示当前下载任务的进度(数字和进度条),当下载任务结束后,显示相关信息:任务成功 or 失败、保存的位置。

Progress({ value: this.curProgressValue })    .width('90%')    .color(Color.Blue)    .margin(10)

Text 显示相关下载信息:

Text('实时下载大小: ' + this.curTaskDownloadedSize + ' B').width('90%').fontSize(25).margin(10)Text('当前任务大小: ' + this.curTaskTotalSize + ' B').width('90%').fontSize(25).margin(10)Text('下载储存路径:').width('90%').fontSize(25).margin({ left: 10, right: 10, top: 10, bottom: 5 })

定义 Image 组件,获取保存路径显示下载的媒体(仅当图片)。

这里访问路径使用的是 downloadInfo 中的 filePath 属性,即内部储存路径。

// downloadInfoList:string[] 保存下载历史的路径ForEach(this.downloadInfoList, item => {    Flex({ justifyContent: FlexAlign.Center }) {        Image(item)            .backgroundColor('#ccc')            .margin(5)            .width('25%')            .aspectRatio(1)            .alignSelf(ItemAlign.Start)            .objectFit(ImageFit.ScaleDown)        Text(item).fontSize(15).padding(10).width('70%')    }.width('95%')}, item => item)

同时,可以完美地运用上我此前封装好的文件管理器组件-FilerBall​​​,来检验我们文件下载保存的位置,以及查看更详细的文件信息。

演示图:借助 FilerBall 组件检验:

这里设置 images、video、file 都保存在沙箱访问路径 internal://cache 的 myDownload/ 下。

Image 回显:

代码如下:

downloadDemo(downloadUrl: string, saveUrl?: string) {    var self = this    var clearListeners = function () {        self.downloadTask.off('progress')        self.downloadTask.off('fail')        self.downloadTask.off('remove')        self.downloadTask.off('complete')    }    let downloadConfig: request.DownloadConfig = {        url: downloadUrl,        filePath: 'myDownload/' + saveUrl,        enableMetered: true,        enableRoaming: true,        description: 'Download Test',    }    request.download(downloadConfig, (err, data) => {        if (err) {            console.info('xxx--- Failed to request the download. Cause: ' + JSON.stringify(err))            return        }        let downloadInfoFilePath        this.curProgressValue = 0        this.mes = '开始'        this.downloadTask = data        this.downloadTask.query().then((downloadInfo: request.DownloadInfo) => {            downloadInfoFilePath = downloadInfo.filePath            this.downloadTask.on('progress', (receiveSize: number, totalSize: number) => {                this.curProgressValue = (receiveSize / totalSize) * 100                this.curTaskDownloadedSize = receiveSize                this.curTaskTotalSize = totalSize            })            console.info('xxx--- Download task queried. Data:' + JSON.stringify(downloadInfo))        }).catch((err) => {            console.info('xxx--- Failed to query the download task. Cause:' + JSON.stringify(err))        })        this.downloadTask.on('fail', (err) => {            clearListeners()            this.curProgressValue = 0            this.mes = '失败'        })        this.downloadTask.on('remove', () => {            clearListeners()            this.curProgressValue = 0            this.mes = '取消'        })        this.downloadTask.on('complete', () => {            clearListeners()            this.curProgressValue = 100            this.mes = '完成'            // downloadInfoList保存下载历史的路径            this.downloadInfoList.push(downloadInfoFilePath)        })    })}

ets 使用示例:

Button('下载视频(小)', { type: ButtonType.Capsule })    .width('90%')    .height(50)    .margin(10)    .onClick(() => {    this.curProgressValue = this.curTaskDownloadedSize = this.curTaskTotalSize = 0    this.downloadDemo(';, 'video/')})

标签: #js下载进度 #下载文件jsjquery