1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import common from '@ohos.app.ability.common'; 17import request from '@ohos.request'; 18import promptAction from '@ohos.promptAction'; 19import { logger } from '../utils/Logger'; 20import { TOAST_BOTTOM, TASK_MAX } from '../utils/Constants'; 21 22const TAG: string = 'RequestDownload'; 23 24class RequestDownload { 25 private context: common.UIAbilityContext | undefined = undefined; 26 private waitList: Array<string[]> = []; 27 private downloadTask: request.agent.Task | undefined = undefined; 28 29 constructor() { 30 setInterval(() => { 31 this.flushBackgroundTask() 32 }, 2000); 33 } 34 35 async downloadFilesBackground(folder: string, files: Array<string>) { 36 logger.info(TAG, 'downloadFiles'); 37 this.context = getContext(this) as common.UIAbilityContext; 38 files.forEach((item: string) => { 39 this.waitList.push([folder, item]); 40 }); 41 } 42 43 async flushBackgroundTask() { 44 let tasks = await request.agent.search({ 45 state: request.agent.State.RUNNING 46 }); 47 if (tasks.length < TASK_MAX && this.waitList.length > 0) { 48 let downloadList: Array<string[]> = []; 49 if (this.waitList.length <= TASK_MAX - tasks.length) { 50 downloadList = this.waitList; 51 this.waitList = []; 52 } else { 53 downloadList = this.waitList.slice(0, TASK_MAX - tasks.length); 54 this.waitList = this.waitList.slice(TASK_MAX - tasks.length, this.waitList.length); 55 } 56 logger.info(TAG, `this.waitList = ${JSON.stringify(this.waitList)}`); 57 this.createBackgroundTask(downloadList); 58 } 59 } 60 61 async createBackgroundTask(downloadList: Array<string[]>) { 62 if (this.context === undefined) { 63 return; 64 } 65 for (let i = 0; i < downloadList.length; i++) { 66 try { 67 let splitUrl = downloadList[i][1].split('//')[1].split('/'); 68 let downloadConfig: request.agent.Config = { 69 action: request.agent.Action.DOWNLOAD, 70 url: downloadList[i][1], 71 method: 'POST', 72 title: 'download', 73 mode: request.agent.Mode.BACKGROUND, 74 network: request.agent.Network.ANY, 75 saveas: `./${downloadList[i][0]}/${splitUrl[splitUrl.length-1]}`, 76 overwrite: true, 77 gauge: true 78 } 79 let downTask = await request.agent.create(this.context, downloadConfig); 80 await downTask.start(); 81 } catch (err) { 82 logger.error(TAG, `task err, err = ${JSON.stringify(err)}`); 83 this.waitList.push(downloadList[i]); 84 } 85 } 86 } 87 88 async downloadFile(folder: string, url: string, callback: (progress: number, isSuccess: boolean) => void) { 89 logger.info(TAG, 'downloadFile'); 90 // 查询到存在正在执行的下载任务,提示并返回 91 let tasks = await request.agent.search({ 92 state: request.agent.State.RUNNING, 93 action: request.agent.Action.DOWNLOAD, 94 mode: request.agent.Mode.FOREGROUND 95 }); 96 if (tasks.length > 0) { 97 promptAction.showToast({ message: $r('app.string.have_download_task_tips'), bottom: TOAST_BOTTOM }); 98 return; 99 } 100 let splitUrl = url.split('//')[1].split('/'); 101 let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; 102 let downloadConfig: request.agent.Config = { 103 action: request.agent.Action.DOWNLOAD, 104 url: url, 105 method: 'POST', 106 title: 'download', 107 mode: request.agent.Mode.FOREGROUND, 108 network: request.agent.Network.ANY, 109 saveas: `./${folder}/${splitUrl[splitUrl.length-1]}`, 110 overwrite: true 111 } 112 logger.info(TAG, `downloadFile, downloadConfig = ${JSON.stringify(downloadConfig)}`); 113 try { 114 this.downloadTask = await request.agent.create(context, downloadConfig); 115 this.downloadTask.on('progress', (progress: request.agent.Progress) => { 116 logger.info(TAG, `progress, progress = ${progress.processed} ${progress.state}`); 117 let processed = Number(progress.processed.toString()).valueOf(); 118 let size = progress.sizes[0]; 119 let process: number = Math.floor(processed / size * 100); 120 if (process < 100) { 121 callback(process, false); 122 } 123 }) 124 this.downloadTask.on('completed', (progress: request.agent.Progress) => { 125 logger.info(TAG, `download complete, file= ${url}, progress = ${progress.processed}`); 126 callback(100, true); 127 this.deleteTask(); 128 }) 129 this.downloadTask.on('failed', async (progress: request.agent.Progress) => { 130 if (this.downloadTask) { 131 let taskInfo = await request.agent.show(this.downloadTask.tid); 132 logger.info(TAG, `fail, resean = ${taskInfo.reason}, faults = ${JSON.stringify(taskInfo.faults)}`); 133 } 134 callback(100, false); 135 this.deleteTask(); 136 }) 137 await this.downloadTask.start(); 138 } catch (err) { 139 logger.error(TAG, `task err, err = ${JSON.stringify(err)}`); 140 callback(100, false); 141 } 142 } 143 144 async deleteTask() { 145 if (this.downloadTask) { 146 try { 147 this.downloadTask.off('progress'); 148 this.downloadTask.off('completed'); 149 this.downloadTask.off('failed'); 150 await request.agent.remove(this.downloadTask.tid); 151 } catch (err) { 152 logger.info(TAG, `deleteTask fail, err= ${JSON.stringify(err)}`); 153 } 154 } 155 156 this.downloadTask = undefined; 157 } 158} 159 160export const requestDownload = new RequestDownload();