
??想了解更多關(guān)于開源的內(nèi)容,請訪問:??
??51CTO 開源基礎(chǔ)軟件社區(qū)??
??https://ost.51cto.com??
簡介
在OpenHarmony應(yīng)用開發(fā)中,我們常用兩種方式來實現(xiàn)文件的下載:
- 使用系統(tǒng)能力SystemCapability.Communication.NetStack(@ohos.http)
- 使用系統(tǒng)能力SystemCapability.MiscServices.Download(@ohos.request)
區(qū)別
- 前者下載過程信息不可見,后者會在手機狀態(tài)欄顯示下載會話,并且可被應(yīng)用監(jiān)聽
- 前者請求下載后不會對文件作進(jìn)一步處理,后者會直接保存到指定目錄
使用場景
- 下載大體積文件時監(jiān)聽進(jìn)度
- 文件下載直接到本地保存
- …
文檔傳送門
??HarmonyOS?OpenHarmony
下面,我們基于ArkUI-ts來實現(xiàn)一個下載進(jìn)度條的顯示,以API 8、FA模型為例。
(API 9接口稍有改動,若使用API 9、Stage模型,請參考官方文檔??OpenHarmony??,但基本的代碼思路是不變的。
變動:
- 相比于API 8的FA模型,加入了Context的傳參。
- 增加了uploadFile()、downloadFile()方法,保留upload()、donwload()方法
實現(xiàn)流程
首先配置網(wǎng)絡(luò)權(quán)限(config.json–>module下添加)。
"reqPermissions": [
{
"name": "ohos.permission.INTERNET"
}
],
支持http(config.json下添加)。
"deviceConfig": {
"default": {
"network": {
"cleartextTraffic": true
}
}
},
1、下載配置
導(dǎo)入系統(tǒng)接口。
import request from '@ohos.request'
DownloadConfig
常用的字段配置:
字段 | 解釋 | 必填 |
url | 資源目標(biāo)地址 | 是 |
header | 請求頭配置 | 否 |
filePath | 資源保存路徑 | 否 |
其它的字段配置:
字段 | 解釋 | 必填 |
title | 設(shè)置下載會話標(biāo)題(狀態(tài)欄) | 否 |
description | 設(shè)置下載會話的描述(狀態(tài)欄) | 否 |
networkType | 允許下載的網(wǎng)絡(luò)類型: 0x00000001——流量數(shù)據(jù) 0x00010000——wifi | 否 |
enableRoaming | 是否允許在漫游網(wǎng)絡(luò)中下載 | 否 |
enableMetered | 允許在按流量計費的連接下下載 | 否 |
示例1
例如:通過圖片url下載保存到本地的 internal://cache的myDownload/test.png 路徑,文件名為test.png
let downloadConfig: request.DownloadConfig = {
url: downloadUrl,
filePath: 'myDownload/test.png',
description: 'Download Test',
}
internal://cache是應(yīng)用沙箱路徑,獲取方法:
import featureAbility from "@ohos.ability.featureAbility"
let cacheSandPath = featureAbility.getConext().getCacheDoir()
目前js api只支持在filePath配置在internal://cache下(默認(rèn))
我們有兩種方式可以訪問到下載的文件:一是內(nèi)部儲存目錄storage路徑file目錄;二是只允許本應(yīng)用訪問的沙箱路徑cache目錄
這個知識點在后面的Image顯示會用到。
2、創(chuàng)建下載任務(wù)
let downloadTask
request.download(downloadConfig, (err, data) => {
if (err) {
console.info('xxx--- Failed to request the download. Cause: ' + JSON.stringify(err))
return
}
downloadTask = data
})
3、監(jiān)聽下載事件
request.DownloadTask
方法 | 解釋 |
on/ off(“progress”) | 開啟/關(guān)閉 進(jìn)度 監(jiān)聽,返回當(dāng)前下載大小receivedSize和總大小totalSize |
on / off(‘complete’|‘pause’|‘remove’) | 開啟/關(guān)閉 完成|暫停|取消 監(jiān)聽 |
on / off(‘fail’) | 開啟/關(guān)閉 失敗 監(jiān)聽,返回錯誤碼 |
remove() | 移除下載任務(wù),返回boolean值 |
pause() | 暫停下載任務(wù) |
query() | 查詢下載實時情況,返回Promise<DownloadInfo> |
queryMimeType() | 查詢下載的任務(wù)的 MimeType(媒體類型),返回Promise<string> |
request.DownloadInfo
屬性 | 解釋 |
downloadTotalBytes | 下載的文件的總大?。╥nt bytes) |
downloadedBytes | 實時下載大?。╥nt bytes) |
downloadId | 下載的文件ID |
fileName | 下載的文件名 |
filePath | 存儲文件的URI |
status | 下載狀態(tài)代碼 |
targetURI | 下載文件的URI |
downloadTitle | 下載的文件的標(biāo)題 |
description | 待下載文件的描述信息 |
failedReason | 下載失敗原因(非必有) |
想要實現(xiàn)下載進(jìn)度的監(jiān)聽,從上面的方法我們可以找到對應(yīng)的方法 on(“progress”)。
示例3-1
downloadTask.on('progress', (receiveSize: number, totalSize: number) => {
this.curProgressValue = (receiveSize / totalSize) * 100
this.curTaskDownloadedSize = receiveSize
this.curTaskTotalSize = totalSize
})
經(jīng)過測試發(fā)現(xiàn),直接使用 on(‘progress’)不一定能監(jiān)聽到實時下載大小和總大小,返回值receivedSize和totalSize可能為0。
因此當(dāng)on(“progress”)的返回值為0時,我們可以用另外一個方法 query() 來查詢實時下載中的進(jìn)度信息,或是在query() 中使用on(‘progress’)。
示例3-2
進(jìn)度的監(jiān)聽
let downloadInfoFilePath:string = ''
downloadTask.query().then((downloadInfo:request.DownloadInfo) => {
downloadInfoFilePath = downloadInfo.filePath // 此處返回的路徑不同于應(yīng)用沙箱路徑
this.downloadTask = data
this.downloadTask.on('progress', (receiveSize: number, totalSize: number) => {
this.curProgressValue = (receiveSize / totalSize) * 100 // 進(jìn)度條Progress屬性值
this.curTaskDownloadedSize = receiveSize // 實時下載大小
this.curTaskTotalSize = totalSize // 總大小
})
/* 或使用query返回的downloadInfo獲取下載進(jìn)度信息
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事件的監(jiān)聽。
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)
})
})
4、下載結(jié)果反饋
定義一個Progress組件來顯示當(dāng)前下載任務(wù)的進(jìn)度(數(shù)字和進(jìn)度條),當(dāng)下載任務(wù)結(jié)束后,顯示相關(guān)信息:任務(wù)成功or失敗、保存的位置。
Progress({ value: this.curProgressValue })
.width('90%')
.color(Color.Blue)
.margin(10)
Text顯示相關(guān)下載信息。
Text('實時下載大小: ' + this.curTaskDownloadedSize + ' B').width('90%').fontSize(25).margin(10)
Text('當(dāng)前任務(wù)大小: ' + this.curTaskTotalSize + ' B').width('90%').fontSize(25).margin(10)
Text('下載儲存路徑:').width('90%').fontSize(25).margin({ left: 10, right: 10, top: 10, bottom: 5 })
定義Image組件,獲取保存路徑顯示下載的媒體(僅當(dāng)圖片)。
這里訪問路徑使用的是downloadInfo中的filePath屬性,即內(nèi)部儲存路徑。
// 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)
同時,可以完美地運用上我在這篇文章 #創(chuàng)作者激勵#【FFH】自制ArkUI組件-文件管理器(二)懸浮小球 封裝好的 文件管理器組件-FilerBall 來檢驗我們文件下載保存的位置,以及查看更詳細(xì)的文件信息。
演示圖
下載大文件(視頻)時
作者激勵【FFH】ArkUI request API實現(xiàn)下載進(jìn)度獲取及顯示-開源基礎(chǔ)軟件社區(qū) #創(chuàng)作者激勵【FFH】ArkUI request API實現(xiàn)下載進(jìn)度獲取及顯示-開源基礎(chǔ)軟件社區(qū)](https://dl-harmonyos.51cto.com/images/202303/c4a52c584ac5b92b260680a5c48b41fe8df818.jpg?x-oss-process=image/resize,w_250,h_440)
這里設(shè)置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('https://media.w3.org/2010/05/sintel/trailer.mp4', 'video/')
})
頁面代碼放在附件資源。
https://ost.51cto.com/resource/2679。
??想了解更多關(guān)于開源的內(nèi)容,請訪問:??
??51CTO 開源基礎(chǔ)軟件社區(qū)??
??https://ost.51cto.com??