1e41f4b71Sopenharmony_ci# Improving File Upload and Download Performance 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## Overview 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ciFile transfer performance is critical to efficient data exchange between the client and server. An application with poor data exchange performance prolongs the loading process and may even cause screen freezing, delivering a poor user experience. On the contrary, efficient data exchange makes an application smoother. 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciThis topic describes two key technologies for upload/download and network requests: data compression and resumable download. Both technologies accelerate upload and download speed, reduce bandwidth usage, and boost data transmission efficiency. 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ci## Upload and Download APIs 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ciYou can use the APIs provided by the [@ohos.net.http](../reference/apis-network-kit/js-apis-http.md) and [@ohos.request](../reference/apis-basic-services-kit/js-apis-request.md) modules to implement file upload and download. The [@ohos.net.http](../reference/apis-network-kit/js-apis-http.md) module provides the basic HTTP data request capability, which is not described in this topic. The [@ohos.request](../reference/apis-basic-services-kit/js-apis-request.md) module provides applications with basic upload, download, and background transmission agent capabilities. This module has the default concurrency capability of the task management system. It simplifies the implementation and management of downloads, and improves the security of data transmission. It also integrates the notification mechanism, and supports task status and progress query. It features flexibility, efficiency, scalability, reliability, consistency, and security. 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ciSpecifically, the [@ohos.request (Upload and Download)](../reference/apis-basic-services-kit/js-apis-request.md) module provides the following functionalities: 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ci- Task management: The operations include creating, pausing, resuming, and deleting tasks, uploading and downloading files, and sending system notifications. The created tasks are classified into foreground tasks and background tasks. Foreground tasks are synchronous, can be displayed on modal screens, and follow the application lifecycle. Generally, a foreground task involves a small volume of data and can be completed within a short period of time. Examples are posting a WeChat Moment. Foreground tasks usually have a high priority and require more bandwidth resources. Background tasks are asynchronous, and can be displayed on any screen. Generally, a foreground task carries relatively large data and is time consuming. Examples are caching a movie and synchronizing hundreds of megabytes of data or even several GB of data. Background tasks have a low priority and are irrelevant to the application lifecycle. 16e41f4b71Sopenharmony_ci 17e41f4b71Sopenharmony_ci- Task query management: The system can query all tasks or information about the specified task, filter upload or download tasks, tasks within a time segment, foreground tasks, or background tasks, and clear the specified task. An application can query information about the specified task and specified hidden task. 18e41f4b71Sopenharmony_ci 19e41f4b71Sopenharmony_ci- Automatic task resumption: A task is automatically started or resumed when the network conditions are met. (The HTTP server must support resumable download.) 20e41f4b71Sopenharmony_ci 21e41f4b71Sopenharmony_ci- Security and privacy protection: The operations include network permission check, encrypted storage of task information, system API check, query and hiding of sensitive task fields (by both system APIs and public APIs), identification of traversal attacks, DoS attacks, zombie tasks, and malicious silent background tasks, and system-managed API permission. In addition, public APIs are allowed only to operate tasks created by themselves. 22e41f4b71Sopenharmony_ci 23e41f4b71Sopenharmony_ci- Log: The debug mode and release mode are provided. In debug mode, all logs about memory modification, disk read/write, network read/write, and logic branches can be printed. In release mode, only logs related to task failures and service exceptions are printed. 24e41f4b71Sopenharmony_ci 25e41f4b71Sopenharmony_ci- Retry upon failure: In case of unrecoverable failures, no retry is provided. In case of recoverable failures, such as network disconnection and network type mismatch, the task enters the queue and waits for network recovery. If the failure cause is network timeout, the task is retried once, and if network timeout is reported again, the task fails. 26e41f4b71Sopenharmony_ci 27e41f4b71Sopenharmony_ci- On-demand service and stop: Upload and download do not automatically start with the system. When your application proactively calls any APIs, upload and download automatically start. The network connection event triggers the start of upload and download. If no task is being processed or a task is waiting for network recovery in the queue, the system checks the queue 10 seconds later. If no task is being processed, the system instructs SAMGR to stop and uninstall the upload and download service. During service exit, new API requests may fail. In this case, check the service status on the client and retry to start the service as required. 28e41f4b71Sopenharmony_ci 29e41f4b71Sopenharmony_ci- Notification: Progress notifications are sent from the start to the end of a task. The notifications are triggered at a fixed interval, which is 1 second for a foreground task and 3 seconds for a background task. A progress notification is required for each change of the task status. A dedicated progress notification is triggered when the task is complete or fails. A suppression switch is also provided. You can turn on the switch during task creation to prevent frequent notifications. 30e41f4b71Sopenharmony_ci 31e41f4b71Sopenharmony_ci 32e41f4b71Sopenharmony_ci### State Transition of a Download Task 33e41f4b71Sopenharmony_ci 34e41f4b71Sopenharmony_ciWhen you use [@ohos.request](../reference/apis-basic-services-kit/js-apis-request.md) to execute a download task, the task has the following states: initial, ready, suspended, waiting, successful, and failed. You can call **create()** **start()**, **pause()**, **resume()**, **remove()**, and **stop()** to operate the task. The task result includes final-failed, final-completed, and recoverable-failed. You can also query the task state. 35e41f4b71Sopenharmony_ci 36e41f4b71Sopenharmony_ci**Figure 1** Module flowchart 37e41f4b71Sopenharmony_ci 38e41f4b71Sopenharmony_ci 39e41f4b71Sopenharmony_ci 40e41f4b71Sopenharmony_ci## Typical Scenarios and Solutions 41e41f4b71Sopenharmony_ci 42e41f4b71Sopenharmony_ci**Scenario 1: Uploading Trivial Files on a Low-Bandwidth Network** 43e41f4b71Sopenharmony_ci 44e41f4b71Sopenharmony_ciIn an environment with poor network connection and low bandwidth, establishing an HTTP connection may be time-consuming. In this case, you can use [data compression](#data-compression) to speed up page loading and reduce the number of HTTP requests and data traffic. 45e41f4b71Sopenharmony_ci 46e41f4b71Sopenharmony_ci**Scenario 2: Processing a Large Number of Resources** 47e41f4b71Sopenharmony_ci 48e41f4b71Sopenharmony_ciApp store and web disk applications usually involve the transfer of a large volume of files. After the application resumes from a pause or network disconnection, restart the upload or download from the beginning may take a lot of time. To address this scenario, you can use [resumable transfer](#resumable-transfer). 49e41f4b71Sopenharmony_ci 50e41f4b71Sopenharmony_ci### Data Compression 51e41f4b71Sopenharmony_ci 52e41f4b71Sopenharmony_ciData compression enables the system to compress data in your application, thereby reducing storage space and data transmission volume, saving bandwidth, and improving loading speed. It plays an important role in network transmission and storage, especially in scenarios of frequent data transmission or processing of a large amount of data. 53e41f4b71Sopenharmony_ci 54e41f4b71Sopenharmony_ciIn application development, common data compression technologies are classified into the following types: 55e41f4b71Sopenharmony_ci 56e41f4b71Sopenharmony_ci- Lossy compression: applies only to images, videos, and audio files. It decreases the file size by reducing the image/video resolution or the audio quality to shorten the loading time and lower the bandwidth consumption. 57e41f4b71Sopenharmony_ci- Lossless compression: You can use [@ohos.zlib (Zip)](../reference/apis-basic-services-kit/js-apis-zlib.md) to pack and compress fragmented files, thereby reducing the number of upload requests. You can use cache for large files. Specifically, the server caches the MD5 value of the large file that has been uploaded, and the client, before uploading a large file, pre-generates an MD5 value and transfers it to the server for comparison. If the MD5 values are the same, the file exists on the server, and the file does not need to be uploaded again. 58e41f4b71Sopenharmony_ci 59e41f4b71Sopenharmony_ci 60e41f4b71Sopenharmony_ciThe following uses uploading images in batches from Gallery as an example to describe the technology related to lossless compression. 61e41f4b71Sopenharmony_ci 62e41f4b71Sopenharmony_ci**Figure 2** Uploading images from Gallery 63e41f4b71Sopenharmony_ci 64e41f4b71Sopenharmony_ci 65e41f4b71Sopenharmony_ci 66e41f4b71Sopenharmony_ciThe table below lists the test results of batch image uploading on the RK device. (For each image, the resolution is 480 x 640, the bit depth is 24, and the average size is 50 to 120 KB). 67e41f4b71Sopenharmony_ci 68e41f4b71Sopenharmony_ci| Image Count| Time Required Before Optimization (ms)| Time Required After Optimization (ms)| 69e41f4b71Sopenharmony_ci| --- | --- | ---| 70e41f4b71Sopenharmony_ci| 10 | 470 | 526 | 71e41f4b71Sopenharmony_ci| 20 | 1124 | 1091 | 72e41f4b71Sopenharmony_ci| ... | ... | ... | 73e41f4b71Sopenharmony_ci| 50 | 2379 | 2138 | 74e41f4b71Sopenharmony_ci| 80 | 3950 | 3258 | 75e41f4b71Sopenharmony_ci| ... | ... | ... | 76e41f4b71Sopenharmony_ci| 100 | 5276 | 3909 | 77e41f4b71Sopenharmony_ci 78e41f4b71Sopenharmony_ci**Figure 3** Comparison between the image count and upload duration 79e41f4b71Sopenharmony_ci 80e41f4b71Sopenharmony_ci 81e41f4b71Sopenharmony_ci 82e41f4b71Sopenharmony_ciThe time required for uploading varies greatly according to the network status. In this example, the minimum value of multiple measurement results is used. According to the data, before the optimization, the time required increases linearly as the number of images increase. After the optimization, the time difference is not obvious when the number of images is small, as compression consumes extra time. However, as the number of images increases, the time difference becomes obvious. 83e41f4b71Sopenharmony_ci 84e41f4b71Sopenharmony_ciTo implement data compression, proceed as follows: 85e41f4b71Sopenharmony_ci 86e41f4b71Sopenharmony_ci1. Import the modules. 87e41f4b71Sopenharmony_ci 88e41f4b71Sopenharmony_ci ```ts 89e41f4b71Sopenharmony_ci import common from '@ohos.app.ability.common'; 90e41f4b71Sopenharmony_ci import fs from '@ohos.file.fs'; 91e41f4b71Sopenharmony_ci import zlib from '@ohos.zlib'; 92e41f4b71Sopenharmony_ci ``` 93e41f4b71Sopenharmony_ci 94e41f4b71Sopenharmony_ci2. Create a class related to compression and upload. 95e41f4b71Sopenharmony_ci 96e41f4b71Sopenharmony_ci ```ts 97e41f4b71Sopenharmony_ci class ZipUpload { 98e41f4b71Sopenharmony_ci // Storage URI before the task is created. 99e41f4b71Sopenharmony_ci private waitList: Array<string> = []; 100e41f4b71Sopenharmony_ci // URIs of the images to upload. 101e41f4b71Sopenharmony_ci private fileUris: Array<string> = []; 102e41f4b71Sopenharmony_ci ... 103e41f4b71Sopenharmony_ci } 104e41f4b71Sopenharmony_ci ``` 105e41f4b71Sopenharmony_ci 106e41f4b71Sopenharmony_ci3. Create a temporary folder to receive images from Gallery, compress the temporary folder, and add it to the list to be uploaded. 107e41f4b71Sopenharmony_ci 108e41f4b71Sopenharmony_ci ```ts 109e41f4b71Sopenharmony_ci // Compress the images. 110e41f4b71Sopenharmony_ci async zipUploadFiles(fileUris: Array<string>): Promise<void> { 111e41f4b71Sopenharmony_ci this.context = getContext(this) as common.UIAbilityContext; 112e41f4b71Sopenharmony_ci let cacheDir = this.context.cacheDir; 113e41f4b71Sopenharmony_ci let tempDir = fs.mkdtempSync(`${cacheDir}/XXXXXX`); 114e41f4b71Sopenharmony_ci // Put the image URIs into the fileUris, and traverse and copy the images to the temporary folder. 115e41f4b71Sopenharmony_ci for (let i = 0; i < fileUris.length; i++) { 116e41f4b71Sopenharmony_ci let fileName = fileUris[i].split('/').pop(); 117e41f4b71Sopenharmony_ci let resourceFile: fs.File = fs.openSync(fileUris[i], fs.OpenMode.READ_ONLY); 118e41f4b71Sopenharmony_ci fs.copyFileSync(resourceFile.fd, `${tempDir}/${fileName}`, 0); 119e41f4b71Sopenharmony_ci fs.closeSync(resourceFile); 120e41f4b71Sopenharmony_ci } 121e41f4b71Sopenharmony_ci // Compress the temporary folder into test.zip. 122e41f4b71Sopenharmony_ci let options: zlib.Options = { 123e41f4b71Sopenharmony_ci level: zlib.CompressLevel.COMPRESS_LEVEL_DEFAULT_COMPRESSION, 124e41f4b71Sopenharmony_ci memLevel: zlib.MemLevel.MEM_LEVEL_DEFAULT, 125e41f4b71Sopenharmony_ci strategy: zlib.CompressStrategy.COMPRESS_STRATEGY_DEFAULT_STRATEGY 126e41f4b71Sopenharmony_ci }; 127e41f4b71Sopenharmony_ci let data = await zlib.compressFile(tempDir, `${cacheDir}/test.zip`, options); 128e41f4b71Sopenharmony_ci // Delete the temporary folder. 129e41f4b71Sopenharmony_ci fs.rmdirSync(tempDir); 130e41f4b71Sopenharmony_ci // Place the generated .zip package in the transmission queue. 131e41f4b71Sopenharmony_ci this.waitList.push(`${cacheDir}/test.zip`); 132e41f4b71Sopenharmony_ci } 133e41f4b71Sopenharmony_ci ``` 134e41f4b71Sopenharmony_ci 135e41f4b71Sopenharmony_ci### Resumable Transfer 136e41f4b71Sopenharmony_ci 137e41f4b71Sopenharmony_ciTo empower resumable download, both the application and the server must use proper technologies for collaboration. You do not need to implement the code of resumable download. Instead, you only need to properly configure the SDK. 138e41f4b71Sopenharmony_ci 139e41f4b71Sopenharmony_ciYou can use the following APIs on the application side: 140e41f4b71Sopenharmony_ci 141e41f4b71Sopenharmony_ci- [@ohos.file.fs (File Management)](../reference/apis-core-file-kit/js-apis-file-fs.md): processes file upload operations, for example, reading file content, slicing files, and combining file slices. 142e41f4b71Sopenharmony_ci- [@ohos.file.hash (File Hash Processing)](../reference/apis-core-file-kit/js-apis-file-hash.md): calculates the MD5 value of a file and sends the value to the server for preprocessing. In this way, files can be transferred within seconds, with the accuracy and reliability ensured. 143e41f4b71Sopenharmony_ci- [@ohos.request (Upload and Download)](../reference/apis-basic-services-kit/js-apis-request.md): implements file upload and resumable upload. 144e41f4b71Sopenharmony_ci 145e41f4b71Sopenharmony_ciYou can use the following technologies on the server: 146e41f4b71Sopenharmony_ci 147e41f4b71Sopenharmony_ci- Range support: The server must support requests carrying the **Range** field to facilitate resumable file upload and download. 148e41f4b71Sopenharmony_ci- File verification: Implement file verification to ensure that the file transfer can be resumed after an interruption. 149e41f4b71Sopenharmony_ci 150e41f4b71Sopenharmony_ci 151e41f4b71Sopenharmony_ciBy combining technologies on the application side and server side, efficient and reliable resumable transfer can be implemented, delivering a better user experience and ensuring stable data transmission. 152e41f4b71Sopenharmony_ci 153e41f4b71Sopenharmony_ciThis topic provides code snippet for resumable upload in the background upload scenario, which is described in the sample [Upload and Download](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Connectivity/UploadAndDownLoad). You can refer to the sample for the complete code. 154e41f4b71Sopenharmony_ci 155e41f4b71Sopenharmony_ci#### File Upload 156e41f4b71Sopenharmony_ci 157e41f4b71Sopenharmony_ciYou can use the **request.agent** API in [@ohos.request (Upload and Download)](../reference/apis-basic-services-kit/js-apis-request.md) to implement automatic pause, resume, and retry operations in resumable upload scenarios. It frees you from manually slicing a file and recording the slice information. Figure 4 shows the flowchart. 158e41f4b71Sopenharmony_ci 159e41f4b71Sopenharmony_ci**Figure 4** Flowchart of resumable upload 160e41f4b71Sopenharmony_ci 161e41f4b71Sopenharmony_ci 162e41f4b71Sopenharmony_ci 163e41f4b71Sopenharmony_ciTo implement resumable upload, proceed as follows: 164e41f4b71Sopenharmony_ci 165e41f4b71Sopenharmony_ciThe complete code is provided in [RequestUpload.ets](https://gitee.com/openharmony/applications_app_samples/blob/master/code/BasicFeature/Connectivity/UploadAndDownLoad/features/uploadanddownload/src/main/ets/upload/RequestUpload.ets). 166e41f4b71Sopenharmony_ci 167e41f4b71Sopenharmony_ci1. Import the modules. 168e41f4b71Sopenharmony_ci 169e41f4b71Sopenharmony_ci ```ts 170e41f4b71Sopenharmony_ci import common from '@ohos.app.ability.common'; 171e41f4b71Sopenharmony_ci import request from '@ohos.request'; 172e41f4b71Sopenharmony_ci ``` 173e41f4b71Sopenharmony_ci 174e41f4b71Sopenharmony_ci2. Create an upload class. 175e41f4b71Sopenharmony_ci 176e41f4b71Sopenharmony_ci ```ts 177e41f4b71Sopenharmony_ci class Upload { 178e41f4b71Sopenharmony_ci // Background task. 179e41f4b71Sopenharmony_ci private backgroundTask: request.agent.Task | undefined = undefined; 180e41f4b71Sopenharmony_ci // Storage URI before the task is created. 181e41f4b71Sopenharmony_ci private waitList: Array<string> = []; 182e41f4b71Sopenharmony_ci ... 183e41f4b71Sopenharmony_ci } 184e41f4b71Sopenharmony_ci ``` 185e41f4b71Sopenharmony_ci 186e41f4b71Sopenharmony_ci3. Generate an MD5 value and upload it to the server for verification. 187e41f4b71Sopenharmony_ci 188e41f4b71Sopenharmony_ci ```ts 189e41f4b71Sopenharmony_ci async checkFileExist(fileUri: string): Promise<boolean> { 190e41f4b71Sopenharmony_ci let httpRequest = http.createHttp(); 191e41f4b71Sopenharmony_ci // Generate an MD5 value. 192e41f4b71Sopenharmony_ci let md5 = await hash.hash(fileUri, 'md5'); 193e41f4b71Sopenharmony_ci let requestOption: http.HttpRequestOptions = { 194e41f4b71Sopenharmony_ci method: http.RequestMethod.POST, 195e41f4b71Sopenharmony_ci extraData: { 196e41f4b71Sopenharmony_ci 'MD5': md5 197e41f4b71Sopenharmony_ci } 198e41f4b71Sopenharmony_ci } 199e41f4b71Sopenharmony_ci let response = await httpRequest.request('http://XXX.XXX.XXX.XXX/XXXX', requestOption); 200e41f4b71Sopenharmony_ci let result = response.result; 201e41f4b71Sopenharmony_ci let flag = false; 202e41f4b71Sopenharmony_ci ... // Determine whether the file exists based on the data returned by the server. 203e41f4b71Sopenharmony_ci if (flag) { 204e41f4b71Sopenharmony_ci return true; 205e41f4b71Sopenharmony_ci } else { 206e41f4b71Sopenharmony_ci return false; 207e41f4b71Sopenharmony_ci } 208e41f4b71Sopenharmony_ci } 209e41f4b71Sopenharmony_ci ``` 210e41f4b71Sopenharmony_ci 211e41f4b71Sopenharmony_ci4. Configure an agent and create a background upload task. 212e41f4b71Sopenharmony_ci 213e41f4b71Sopenharmony_ci ```ts 214e41f4b71Sopenharmony_ci private config: request.agent.Config = { 215e41f4b71Sopenharmony_ci action: request.agent.Action.UPLOAD, 216e41f4b71Sopenharmony_ci headers: HEADER, 217e41f4b71Sopenharmony_ci url: '', 218e41f4b71Sopenharmony_ci mode: request.agent.Mode.BACKGROUND, 219e41f4b71Sopenharmony_ci method: 'POST', 220e41f4b71Sopenharmony_ci title: 'upload', 221e41f4b71Sopenharmony_ci network: request.agent.Network.ANY, 222e41f4b71Sopenharmony_ci data: [], 223e41f4b71Sopenharmony_ci token: 'UPLOAD_TOKEN' 224e41f4b71Sopenharmony_ci } 225e41f4b71Sopenharmony_ci ... 226e41f4b71Sopenharmony_ci // Convert the URI. 227e41f4b71Sopenharmony_ci private async getFilesAndData(cacheDir: string, fileUris: Array<string>): Promise<Array<request.agent.FormItem>> { 228e41f4b71Sopenharmony_ci ... 229e41f4b71Sopenharmony_ci } 230e41f4b71Sopenharmony_ci // Create a background task to upload the file. 231e41f4b71Sopenharmony_ci async createBackgroundTask(fileUris: Array<string>) { 232e41f4b71Sopenharmony_ci // Obtain the URL. 233e41f4b71Sopenharmony_ci this.config.url = 'http://XXX.XXX.XXX.XXX'; 234e41f4b71Sopenharmony_ci this.config.mode = request.agent.Mode.BACKGROUND; 235e41f4b71Sopenharmony_ci let tempData = await this.getFilesAndData(this.context.cacheDir, fileUris); 236e41f4b71Sopenharmony_ci // Check whether the file is empty. 237e41f4b71Sopenharmony_ci for (let i = 0; i < tempData.length; i++) { 238e41f4b71Sopenharmony_ci let flag = await this.checkFileExist(`${this.context.cacheDir}/${tempData[i].name}`); 239e41f4b71Sopenharmony_ci if (!flag) { 240e41f4b71Sopenharmony_ci this.config.data.push(tempData[i]) 241e41f4b71Sopenharmony_ci } 242e41f4b71Sopenharmony_ci } 243e41f4b71Sopenharmony_ci let isFileExist = await this.checkFileExist(`${this.context.cacheDir}/${this.config.data[0].name}`); 244e41f4b71Sopenharmony_ci if (this.config.data.length === 0) { 245e41f4b71Sopenharmony_ci return; 246e41f4b71Sopenharmony_ci } 247e41f4b71Sopenharmony_ci this.backgroundTask = await request.agent.create(this.context, this.config); 248e41f4b71Sopenharmony_ci } 249e41f4b71Sopenharmony_ci ``` 250e41f4b71Sopenharmony_ci 251e41f4b71Sopenharmony_ci5. Start the task. 252e41f4b71Sopenharmony_ci 253e41f4b71Sopenharmony_ci ```ts 254e41f4b71Sopenharmony_ci await this.backgroundTask.start(); 255e41f4b71Sopenharmony_ci ``` 256e41f4b71Sopenharmony_ci 257e41f4b71Sopenharmony_ci6. Pause the task. 258e41f4b71Sopenharmony_ci 259e41f4b71Sopenharmony_ci ```ts 260e41f4b71Sopenharmony_ci async pause() { 261e41f4b71Sopenharmony_ci if (this.backgroundTask === undefined) { 262e41f4b71Sopenharmony_ci return; 263e41f4b71Sopenharmony_ci } 264e41f4b71Sopenharmony_ci await this.backgroundTask.pause(); 265e41f4b71Sopenharmony_ci } 266e41f4b71Sopenharmony_ci ``` 267e41f4b71Sopenharmony_ci 268e41f4b71Sopenharmony_ci7. Resume the task. 269e41f4b71Sopenharmony_ci 270e41f4b71Sopenharmony_ci ```ts 271e41f4b71Sopenharmony_ci async resume() { 272e41f4b71Sopenharmony_ci if (this.backgroundTask === undefined) { 273e41f4b71Sopenharmony_ci return; 274e41f4b71Sopenharmony_ci } 275e41f4b71Sopenharmony_ci await this.backgroundTask.resume(); 276e41f4b71Sopenharmony_ci } 277e41f4b71Sopenharmony_ci ``` 278e41f4b71Sopenharmony_ci 279e41f4b71Sopenharmony_ci#### File Download 280e41f4b71Sopenharmony_ci 281e41f4b71Sopenharmony_ciYou can call **request.agent** in resumable download scenarios. This API implements resumable download based on the **Range** field in the HTTP header. This field is automatically set when a task is resumed and requires no additional configuration. 282e41f4b71Sopenharmony_ci 283e41f4b71Sopenharmony_ci> **Introduction to Range** 284e41f4b71Sopenharmony_ci> 285e41f4b71Sopenharmony_ci> The **Range** field in the HTTP protocol allows the server to send an HTTP message 286e41f4b71Sopenharmony_ci> to the client to request part of the data rather than the entire resource. 287e41f4b71Sopenharmony_ci> 288e41f4b71Sopenharmony_ci> The format of the field is Range: \<unit>=\<start>-\<end>, where **\<unit>** indicates the range unit (bytes usually), and **\<start>** and **\<end>** indicate the start byte and end byte of the message, respectively. 289e41f4b71Sopenharmony_ci> 290e41f4b71Sopenharmony_ci> The syntax of **Range** is as follows: 291e41f4b71Sopenharmony_ci> ```ts 292e41f4b71Sopenharmony_ci> // From range-start to the end of the file. 293e41f4b71Sopenharmony_ci> Range: <unit>=<range-start>- 294e41f4b71Sopenharmony_ci> // From range-start to range-end. 295e41f4b71Sopenharmony_ci> Range: <unit>=<range-start>-<range-end> 296e41f4b71Sopenharmony_ci> // Multiple parts, separated by commas (,). 297e41f4b71Sopenharmony_ci> Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end> 298e41f4b71Sopenharmony_ci> 299e41f4b71Sopenharmony_ci> // Example: The file content after 1024 bytes is returned. 300e41f4b71Sopenharmony_ci> Range: bytes=1024- 301e41f4b71Sopenharmony_ci> ``` 302e41f4b71Sopenharmony_ci> The server returns 206 Partial Content if it properly processes the message, and returns other response codes in the case of a failure. The table below lists the common response codes returned by the server. 303e41f4b71Sopenharmony_ci> 304e41f4b71Sopenharmony_ci> | Response Code | Common Cause | 305e41f4b71Sopenharmony_ci> | ------------------ | -----------------| 306e41f4b71Sopenharmony_ci> | 206 Partial Content | The server successfully processes the message and returns the requested range of data.| 307e41f4b71Sopenharmony_ci> | 416 Range Not Satisfiable | The range requested by the client is invalid.| 308e41f4b71Sopenharmony_ci> |200 OK | The server ignores the **Range** field in the header and returns the entire file.| 309e41f4b71Sopenharmony_ci> 310e41f4b71Sopenharmony_ci 311e41f4b71Sopenharmony_ciTo implement resumable download, proceed as follows: 312e41f4b71Sopenharmony_ci 313e41f4b71Sopenharmony_ciThe complete code is provided in [RequestDownload.ets](https://gitee.com/openharmony/applications_app_samples/blob/master/code/BasicFeature/Connectivity/UploadAndDownLoad/features/uploadanddownload/src/main/ets/download/RequestDownload.ets). 314e41f4b71Sopenharmony_ci 315e41f4b71Sopenharmony_ci1. Import the modules. 316e41f4b71Sopenharmony_ci 317e41f4b71Sopenharmony_ci ```ts 318e41f4b71Sopenharmony_ci import common from '@ohos.app.ability.common'; 319e41f4b71Sopenharmony_ci import request from '@ohos.request'; 320e41f4b71Sopenharmony_ci ``` 321e41f4b71Sopenharmony_ci 322e41f4b71Sopenharmony_ci2. Create a download class. 323e41f4b71Sopenharmony_ci 324e41f4b71Sopenharmony_ci ```ts 325e41f4b71Sopenharmony_ci class Download { 326e41f4b71Sopenharmony_ci // Storage URI before the task is created. 327e41f4b71Sopenharmony_ci private waitList: Array<string[]> = []; 328e41f4b71Sopenharmony_ci // Download task. 329e41f4b71Sopenharmony_ci private downloadTask: request.agent.Task | undefined = undefined; 330e41f4b71Sopenharmony_ci // Background task download list. 331e41f4b71Sopenharmony_ci private backgroundDownloadTaskList: Array<request.agent.Task> = []; 332e41f4b71Sopenharmony_ci ... 333e41f4b71Sopenharmony_ci } 334e41f4b71Sopenharmony_ci ``` 335e41f4b71Sopenharmony_ci 336e41f4b71Sopenharmony_ci3. Configure an agent and create a background download task. 337e41f4b71Sopenharmony_ci 338e41f4b71Sopenharmony_ci ```ts 339e41f4b71Sopenharmony_ci async createBackgroundTask(downloadList: Array<string[]>) { 340e41f4b71Sopenharmony_ci let splitUrl = url.split('//')[1].split('/'); 341e41f4b71Sopenharmony_ci let context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; 342e41f4b71Sopenharmony_ci let downloadConfig: request.agent.Config = { 343e41f4b71Sopenharmony_ci action: request.agent.Action.DOWNLOAD, 344e41f4b71Sopenharmony_ci url: url, 345e41f4b71Sopenharmony_ci method: 'POST', 346e41f4b71Sopenharmony_ci title: 'download', 347e41f4b71Sopenharmony_ci mode: request.agent.Mode.FOREGROUND, // Only background tasks can be resumed. 348e41f4b71Sopenharmony_ci network: request.agent.Network.ANY, 349e41f4b71Sopenharmony_ci saveas: `./${folder}/${splitUrl[splitUrl.length-1]}`, 350e41f4b71Sopenharmony_ci overwrite: true 351e41f4b71Sopenharmony_ci } 352e41f4b71Sopenharmony_ci this.downloadTask = await request.agent.create(context, downloadConfig); 353e41f4b71Sopenharmony_ci if (this.backgroundDownloadTaskList.findIndex(task => task.config.url === downTask.config.url) === -1) { 354e41f4b71Sopenharmony_ci this.backgroundDownloadTaskList.push(downTask); 355e41f4b71Sopenharmony_ci } 356e41f4b71Sopenharmony_ci } 357e41f4b71Sopenharmony_ci ``` 358e41f4b71Sopenharmony_ci 359e41f4b71Sopenharmony_ci4. Start the task. 360e41f4b71Sopenharmony_ci 361e41f4b71Sopenharmony_ci ```ts 362e41f4b71Sopenharmony_ci ... 363e41f4b71Sopenharmony_ci await downTask.start(); 364e41f4b71Sopenharmony_ci ... 365e41f4b71Sopenharmony_ci ``` 366e41f4b71Sopenharmony_ci 367e41f4b71Sopenharmony_ci5. Pause the task. 368e41f4b71Sopenharmony_ci 369e41f4b71Sopenharmony_ci ```ts 370e41f4b71Sopenharmony_ci async pause() { 371e41f4b71Sopenharmony_ci if (this.backgroundDownloadTaskList.length === 0) { 372e41f4b71Sopenharmony_ci return; 373e41f4b71Sopenharmony_ci } 374e41f4b71Sopenharmony_ci this.backgroundDownloadTaskList.forEach(async task => { 375e41f4b71Sopenharmony_ci await task.pause(); 376e41f4b71Sopenharmony_ci }) 377e41f4b71Sopenharmony_ci } 378e41f4b71Sopenharmony_ci ``` 379e41f4b71Sopenharmony_ci 380e41f4b71Sopenharmony_ci6. Resume the task. 381e41f4b71Sopenharmony_ci 382e41f4b71Sopenharmony_ci ```ts 383e41f4b71Sopenharmony_ci async resume() { 384e41f4b71Sopenharmony_ci if (this.backgroundDownloadTaskList.length === 0) { 385e41f4b71Sopenharmony_ci return; 386e41f4b71Sopenharmony_ci } 387e41f4b71Sopenharmony_ci this.backgroundDownloadTaskList.forEach(async task => { 388e41f4b71Sopenharmony_ci await task.resume(); 389e41f4b71Sopenharmony_ci }) 390e41f4b71Sopenharmony_ci } 391e41f4b71Sopenharmony_ci ``` 392e41f4b71Sopenharmony_ci 393e41f4b71Sopenharmony_ci7. Stop the task. 394e41f4b71Sopenharmony_ci 395e41f4b71Sopenharmony_ci ```ts 396e41f4b71Sopenharmony_ci async deleteAllBackTasks() { 397e41f4b71Sopenharmony_ci if (this.backgroundDownloadTaskList.length > 0) { 398e41f4b71Sopenharmony_ci this.backgroundDownloadTaskList.forEach(async task => { 399e41f4b71Sopenharmony_ci await request.agent.remove(task.tid); 400e41f4b71Sopenharmony_ci }) 401e41f4b71Sopenharmony_ci this.backgroundDownloadTaskList = []; 402e41f4b71Sopenharmony_ci } 403e41f4b71Sopenharmony_ci } 404e41f4b71Sopenharmony_ci ``` 405e41f4b71Sopenharmony_ci 406