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![Module flowchart](./figures/file-upload-and-download-pic1.png)
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![Uploading images](./figures/file-upload-and-download-pic2.png)
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![Comparison between the image count and upload duration](./figures/file-upload-and-download-pic3.png)
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![Resumable upload](./figures/file-upload-and-download-pic4.png)
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