• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 { BackgroundTaskState, TASK_MAX, TOAST_BOTTOM } 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  private backgroundDownloadTaskList: Array<request.agent.Task> = [];
29
30  constructor() {
31    setInterval(() => {
32      this.flushBackgroundTask()
33    }, 2000);
34  }
35
36  async downloadFilesBackground(folder: string, files: Array<string>) {
37    logger.info(TAG, 'downloadFiles');
38    this.context = getContext(this) as common.UIAbilityContext;
39    files.forEach((item: string) => {
40      this.waitList.push([folder, item]);
41    });
42  }
43
44  async flushBackgroundTask() {
45    let tasks = await request.agent.search({
46      state: request.agent.State.RUNNING
47    });
48    if (tasks.length < TASK_MAX && this.waitList.length > 0) {
49      let downloadList: Array<string[]> = [];
50      if (this.waitList.length <= TASK_MAX - tasks.length) {
51        downloadList = this.waitList;
52        this.waitList = [];
53      } else {
54        downloadList = this.waitList.slice(0, TASK_MAX - tasks.length);
55        this.waitList = this.waitList.slice(TASK_MAX - tasks.length, this.waitList.length);
56      }
57      logger.info(TAG, `this.waitList = ${JSON.stringify(this.waitList)}`);
58      this.createBackgroundTask(downloadList);
59    } else {
60      let state = AppStorage.get<number>('backDownTaskState');
61      logger.info(TAG, `backLists  = ${this.backgroundDownloadTaskList.map(i => i.tid)}`);
62      if (state === BackgroundTaskState.RUNNING) {
63        if (tasks.length === 0) {
64          AppStorage.setOrCreate('backDownTaskState', BackgroundTaskState.NONE);
65          this.backgroundDownloadTaskList = [];
66        }
67      }
68    }
69  }
70
71  async createBackgroundTask(downloadList: Array<string[]>) {
72    if (this.context === undefined) {
73      return;
74    }
75    for (let i = 0; i < downloadList.length; i++) {
76      try {
77        let splitUrl = downloadList[i][1].split('//')[1].split('/');
78        let downloadConfig: request.agent.Config = {
79          action: request.agent.Action.DOWNLOAD,
80          url: downloadList[i][1],
81          method: 'POST',
82          title: 'download',
83          mode: request.agent.Mode.BACKGROUND,
84          network: request.agent.Network.ANY,
85          saveas: `./${downloadList[i][0]}/${splitUrl[splitUrl.length-1]}`,
86          overwrite: true,
87          gauge: true
88        }
89        let downTask = await request.agent.create(this.context, downloadConfig);
90        if (this.backgroundDownloadTaskList.findIndex(task => task.config.url === downTask.config.url) === -1) {
91          this.backgroundDownloadTaskList.push(downTask);
92        }
93        await downTask.start();
94      } catch (err) {
95        logger.error(TAG, `task  err, err  = ${JSON.stringify(err)}`);
96        this.waitList.push(downloadList[i]);
97      }
98    }
99  }
100
101  async downloadFile(folder: string, url: string, callback: (progress: number, isSuccess: boolean) => void) {
102    logger.info(TAG, 'downloadFile');
103    // 查询到存在正在执行的下载任务,提示并返回
104    let tasks = await request.agent.search({
105      state: request.agent.State.RUNNING,
106      action: request.agent.Action.DOWNLOAD,
107      mode: request.agent.Mode.FOREGROUND
108    });
109    if (tasks.length > 0) {
110      promptAction.showToast({ message: $r('app.string.have_download_task_tips'), bottom: TOAST_BOTTOM });
111      return;
112    }
113    let splitUrl = url.split('//')[1].split('/');
114    let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
115    let downloadConfig: request.agent.Config = {
116      action: request.agent.Action.DOWNLOAD,
117      url: url,
118      method: 'POST',
119      title: 'download',
120      mode: request.agent.Mode.FOREGROUND,
121      network: request.agent.Network.ANY,
122      saveas: `./${folder}/${splitUrl[splitUrl.length-1]}`,
123      overwrite: true
124    }
125    logger.info(TAG, `downloadFile, downloadConfig = ${JSON.stringify(downloadConfig)}`);
126    try {
127      this.downloadTask = await request.agent.create(context, downloadConfig);
128      this.downloadTask.on('progress', (progress: request.agent.Progress) => {
129        logger.info(TAG, `progress,  progress = ${progress.processed} ${progress.state}`);
130        let processed = Number(progress.processed.toString()).valueOf();
131        let size = progress.sizes[0];
132        let process: number = Math.floor(processed / size * 100);
133        if (process < 100) {
134          callback(process, false);
135        }
136      })
137      this.downloadTask.on('completed', (progress: request.agent.Progress) => {
138        logger.info(TAG, `download complete, file= ${url}, progress = ${progress.processed}`);
139        callback(100, true);
140        this.deleteTask();
141      })
142      this.downloadTask.on('failed', async (progress: request.agent.Progress) => {
143        if (this.downloadTask) {
144          let taskInfo = await request.agent.show(this.downloadTask.tid);
145          logger.info(TAG, `fail,  resean = ${taskInfo.reason}, faults = ${JSON.stringify(taskInfo.faults)}`);
146        }
147        callback(100, false);
148        this.deleteTask();
149      })
150      await this.downloadTask.start();
151    } catch (err) {
152      logger.error(TAG, `task  err, err  = ${JSON.stringify(err)}`);
153      callback(100, false);
154    }
155  }
156
157  async pauseOrResume() {
158    let state = AppStorage.get<number>('backDownTaskState');
159    if (state === BackgroundTaskState.RUNNING) {
160      await this.pause();
161      AppStorage.setOrCreate('backDownTaskState', BackgroundTaskState.PAUSE);
162    } else if (state === BackgroundTaskState.PAUSE) {
163      await this.resume();
164      AppStorage.setOrCreate('backDownTaskState', BackgroundTaskState.RUNNING);
165    } else {
166      logger.info(TAG, 'this task state is error');
167    }
168  }
169
170  async pause() {
171    logger.info(TAG, 'pause');
172    if (this.backgroundDownloadTaskList.length === 0) {
173      return;
174    }
175    try {
176      this.backgroundDownloadTaskList.forEach(async task => {
177        await task.pause();
178      })
179    } catch (err) {
180      logger.info(TAG, `pause fail,err= ${JSON.stringify(err)}`);
181    }
182  }
183
184  async resume() {
185    logger.info(TAG, 'resume');
186    if (this.backgroundDownloadTaskList.length === 0) {
187      return;
188    }
189    try {
190      this.backgroundDownloadTaskList.forEach(async task => {
191        await task.resume();
192      })
193    } catch (err) {
194      logger.info(TAG, `resume fail,err= ${JSON.stringify(err)}`);
195    }
196  }
197
198  async deleteTask() {
199    if (this.downloadTask) {
200      try {
201        this.downloadTask.off('progress');
202        this.downloadTask.off('completed');
203        this.downloadTask.off('failed');
204        await request.agent.remove(this.downloadTask.tid);
205      } catch (err) {
206        logger.info(TAG, `deleteTask fail, err= ${JSON.stringify(err)}`);
207      }
208    }
209    this.downloadTask = undefined;
210  }
211
212  async deleteAllBackTasks() {
213    if (this.backgroundDownloadTaskList.length > 0) {
214      try {
215        this.backgroundDownloadTaskList.forEach(async task => {
216          await request.agent.remove(task.tid);
217        })
218        this.backgroundDownloadTaskList = [];
219        AppStorage.setOrCreate('backDownTaskState', BackgroundTaskState.NONE);
220      } catch (err) {
221        logger.info(TAG, `deleteAllTask fail, err= ${JSON.stringify(err)}`);
222      }
223    }
224  }
225}
226
227export const requestDownload = new RequestDownload();