1# Uploading and Downloading Application Files 2<!--Kit: Basic Services Kit--> 3<!--Subsystem: Request--> 4<!--Owner: @huaxin05--> 5<!--Designer: @hu-kai45--> 6<!--Tester: @murphy1984--> 7<!--Adviser: @zhang_yixin13--> 8 9This topic describes how to upload an application file to a network server and download a network resource file from a network server to a local application file directory. 10 11## Uploading Application Files 12 13You can use **uploadFile()** in [ohos.request](../../reference/apis-basic-services-kit/js-apis-request.md) to upload local files. The system service proxy implements the upload. In API version 12, the parameter for setting the custom proxy address is added to the **request.agent.create** API. 14 15> **NOTE** 16> 17> · Currently, only files in the **cacheDir** directory can be uploaded using **request.uploadFile**; user public files and files in the **cacheDir** directory can be uploaded together using **request.agent**. 18> 19> · The ohos.permission.INTERNET permission is required for using **ohos.request**. For details about how to request the permission, see [Declaring Permissions](../../security/AccessToken/declare-permissions.md). 20> 21> · The **ohos.request** module does not support proxy packet capture tools such as Charles and Fiddler. 22> 23> · Currently, APIs of the **ohos.request** module cannot be called in sub-threads, such as [TaskPool](../../arkts-utils/taskpool-introduction.md). 24 25The following sample code shows how to upload cache files to the server in two ways: 26 27```ts 28// Method 1: Use request.uploadFile. 29// pages/xxx.ets 30import { common } from '@kit.AbilityKit'; 31import fs from '@ohos.file.fs'; 32import { BusinessError, request } from '@kit.BasicServicesKit'; 33 34@Entry 35@Component 36struct Index { 37 build() { 38 Row() { 39 Column() { 40 Button("Upload").onClick(() => { 41 // Obtain the application file path. 42 // Obtain the context from the component and ensure that the return value of this.getUIContext().getHostContext() is UIAbilityContext. 43 let context = this.getUIContext().getHostContext() as common.UIAbilityContext; 44 let cacheDir = context.cacheDir; 45 46 // Create an application file locally. 47 try { 48 let file = fs.openSync(cacheDir + '/test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 49 fs.writeSync(file.fd, 'upload file test'); 50 fs.closeSync(file); 51 } catch (error) { 52 let err: BusinessError = error as BusinessError; 53 console.error(`Invoke uploadFile failed, code is ${err.code}, message is ${err.message}`); 54 } 55 56 // Configure the upload task. 57 let files: Array<request.File> = [ 58 // "internal://cache" in uri corresponds to the cacheDir directory. 59 { filename: 'test.txt', name: 'test', uri: 'internal://cache/test.txt', type: 'txt' } 60 ] 61 let data: Array<request.RequestData> = [{ name: 'name', value: 'value' }]; 62 let uploadConfig: request.UploadConfig = { 63 url: 'https://xxx', 64 header: { 65 'key1':'value1', 66 'key2':'value2' 67 }, 68 method: 'POST', 69 files: files, 70 data: data 71 } 72 73 // Upload the created application file to the network server. 74 try { 75 request.uploadFile(context, uploadConfig) 76 .then((uploadTask: request.UploadTask) => { 77 uploadTask.on('complete', (taskStates: Array<request.TaskState>) => { 78 for (let i = 0; i < taskStates.length; i++) { 79 console.info(`upload complete taskState: ${JSON.stringify(taskStates[i])}`); 80 } 81 }); 82 }) 83 .catch((err: BusinessError) => { 84 console.error(`Invoke uploadFile failed, code is ${err.code}, message is ${err.message}`); 85 }) 86 } catch (error) { 87 let err: BusinessError = error as BusinessError; 88 console.error(`Invoke uploadFile failed, code is ${err.code}, message is ${err.message}`); 89 } 90 }) 91 } 92 } 93 } 94} 95``` 96 97```ts 98// Method 2: Use request.agent. 99// pages/xxx.ets 100import { common } from '@kit.AbilityKit'; 101import fs from '@ohos.file.fs'; 102import { BusinessError, request } from '@kit.BasicServicesKit'; 103 104@Entry 105@Component 106struct Index { 107 build() { 108 Row() { 109 Column() { 110 Button("Upload").onClick(() => { 111 // Obtain the application file path. 112 // Obtain the context from the component and ensure that the return value of this.getUIContext().getHostContext() is UIAbilityContext. 113 let context = this.getUIContext().getHostContext() as common.UIAbilityContext; 114 let cacheDir = context.cacheDir; 115 116 // Create an application file locally. 117 let file = fs.openSync(cacheDir + '/test.txt', fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); 118 fs.writeSync(file.fd, 'upload file test'); 119 fs.closeSync(file); 120 let attachments: Array<request.agent.FormItem> = [{ 121 name: "test", 122 value: [ 123 { 124 filename: "test.txt", 125 path: cacheDir + '/test.txt', 126 }, 127 ] 128 }]; 129 let config: request.agent.Config = { 130 action: request.agent.Action.UPLOAD, 131 url: 'http://xxx', 132 mode: request.agent.Mode.FOREGROUND, 133 overwrite: true, 134 method: "POST", 135 headers: { 136 'key1':'value1', 137 'key2':'value2' 138 }, 139 data: attachments 140 }; 141 request.agent.create(context, config).then((task: request.agent.Task) => { 142 task.start((err: BusinessError) => { 143 if (err) { 144 console.error(`Failed to start the upload task, Code: ${err.code} message: ${err.message}`); 145 return; 146 } 147 }); 148 task.on('progress', async(progress) => { 149 console.warn(`/Request upload status ${progress.state}, uploaded ${progress.processed}`); 150 }) 151 task.on('completed', async() => { 152 console.warn(`/Request upload completed`); 153 // This method requires the user to manage the task lifecycle. After the task is complete, call the remove method to release the task object. 154 request.agent.remove(task.tid); 155 }) 156 }).catch((err: BusinessError) => { 157 console.error(`Failed to create a upload task, Code: ${err.code}, message: ${err.message}`); 158 }); 159 }) 160 } 161 } 162 } 163} 164 165``` 166 167## Downloading Network Resource Files to an Application Directory 168 169You can use **downloadFile()** in [ohos.request](../../reference/apis-basic-services-kit/js-apis-request.md) to download network resource files to a local application directory. You can use the [ohos.file.fs](../../reference/apis-core-file-kit/js-apis-file-fs.md) APIs to access the downloaded files. For details, see [Accessing Application Files](../../file-management/app-file-access.md). The system service agent downloads the files. In API version 12, you can set the address of the agent in **request.agent.create()**. 170 171> **NOTE** 172> 173> Currently, network resource files can be downloaded only to the application file directory. 174> 175> To use **uploadFile()** in **ohos.request**, you need to [declare permissions](../../security/AccessToken/declare-permissions.md): ohos.permission.INTERNET. 176 177The following sample code shows how to download network resource files to the application file directory in two ways: 178 179```ts 180// Method 1: Use request.downloadFile. 181// pages/xxx.ets 182// Download the network resource file to the local application file directory, and read data from the file. 183import { common } from '@kit.AbilityKit'; 184import fs from '@ohos.file.fs'; 185import { BusinessError, request } from '@kit.BasicServicesKit'; 186import { buffer } from '@kit.ArkTS'; 187 188@Entry 189@Component 190struct Index { 191 build() { 192 Row() { 193 Column() { 194 Button("Download").onClick(() => { 195 // Obtain the application file path. 196 // Obtain the context from the component and ensure that the return value of this.getUIContext().getHostContext() is UIAbilityContext. 197 let context = this.getUIContext().getHostContext() as common.UIAbilityContext; 198 let filesDir = context.filesDir; 199 200 try { 201 request.downloadFile(context, { 202 url: 'https://xxxx/xxxx.txt', 203 filePath: filesDir + '/xxxx.txt' 204 }).then((downloadTask: request.DownloadTask) => { 205 downloadTask.on('complete', () => { 206 console.info('download complete'); 207 let file = fs.openSync(filesDir + '/xxxx.txt', fs.OpenMode.READ_WRITE); 208 let arrayBuffer = new ArrayBuffer(1024); 209 let readLen = fs.readSync(file.fd, arrayBuffer); 210 let buf = buffer.from(arrayBuffer, 0, readLen); 211 console.info(`The content of file: ${buf.toString()}`); 212 fs.closeSync(file); 213 }) 214 }).catch((err: BusinessError) => { 215 console.error(`Invoke downloadTask failed, code is ${err.code}, message is ${err.message}`); 216 }); 217 } catch (error) { 218 let err: BusinessError = error as BusinessError; 219 console.error(`Invoke downloadFile failed, code is ${err.code}, message is ${err.message}`); 220 } 221 }) 222 } 223 } 224 } 225} 226``` 227```ts 228// Method 2: Use request.agent. 229// pages/xxx.ets 230// Download the network resource file to the local application file directory, and read data from the file. 231import { common } from '@kit.AbilityKit'; 232import fs from '@ohos.file.fs'; 233import { BusinessError, request } from '@kit.BasicServicesKit'; 234import { buffer } from '@kit.ArkTS'; 235 236@Entry 237@Component 238struct Index { 239 build() { 240 Row() { 241 Column() { 242 Button("Download").onClick(() => { 243 // Obtain the application file path. 244 // Obtain the context from the component and ensure that the return value of this.getUIContext().getHostContext() is UIAbilityContext. 245 let context = this.getUIContext().getHostContext() as common.UIAbilityContext; 246 let filesDir = context.filesDir; 247 248 let config: request.agent.Config = { 249 action: request.agent.Action.DOWNLOAD, 250 url: 'https://xxxx/test.txt', 251 saveas: 'xxxx.txt', 252 gauge: true, 253 overwrite: true, 254 network: request.agent.Network.WIFI, 255 }; 256 request.agent.create(context, config).then((task: request.agent.Task) => { 257 task.start((err: BusinessError) => { 258 if (err) { 259 console.error(`Failed to start the download task, Code: ${err.code} message: ${err.message}`); 260 return; 261 } 262 }); 263 task.on('progress', async (progress) => { 264 console.warn(`/Request download status ${progress.state}, downloaded ${progress.processed}`); 265 }) 266 task.on('completed', async () => { 267 console.warn(`/Request download completed`); 268 let file = fs.openSync(filesDir + '/xxxx.txt', fs.OpenMode.READ_WRITE); 269 let arrayBuffer = new ArrayBuffer(1024); 270 let readLen = fs.readSync(file.fd, arrayBuffer); 271 let buf = buffer.from(arrayBuffer, 0, readLen); 272 console.info(`The content of file: ${buf.toString()}`); 273 fs.closeSync(file); 274 // This method requires the user to manage the task lifecycle. After the task is complete, call the remove method to release the task object. 275 request.agent.remove(task.tid); 276 }) 277 }).catch((err: BusinessError) => { 278 console.error(`Failed to create a download task, Code: ${err.code}, message: ${err.message}`); 279 }); 280 }) 281 } 282 } 283 } 284} 285 286``` 287 288## Downloading Network Resource Files to the User File 289You can use the [request.agent](../../reference/apis-basic-services-kit/js-apis-request.md#requestagentcreate10) API of [ohos.request](../../reference/apis-basic-services-kit/js-apis-request.md) to download network resource files to the specified user file directory. 290 291> **NOTE** 292> 293> Since API version 20, network resource files can be downloaded to the user file directory. 294 295### Downloading Documents 296 297Call the [save()](../../reference/apis-core-file-kit/js-apis-file-picker.md#save) API of [DocumentViewPicker](../../reference/apis-core-file-kit/js-apis-file-picker.md#documentviewpicker) to save a document and obtain the URI of the user file. Use this URI as the value of the **saveas** field of [Config](../../reference/apis-basic-services-kit/js-apis-request.md#config10) to download the document. 298 299```ts 300import { BusinessError, request } from '@kit.BasicServicesKit'; 301import { picker } from '@kit.CoreFileKit'; 302import { common } from '@kit.AbilityKit'; 303 304@Entry 305@Component 306struct Index { 307 build() { 308 Row() { 309 Column() { 310 Button("Download Document").width("50%").margin({ top: 20 }).height(40).onClick(async () => { 311 312 // Create a documentSaveOptions instance. 313 try { 314 const documentSaveOptions = new picker.DocumentSaveOptions(); 315 // (Optional) Name of the file to save. The default value is empty. 316 documentSaveOptions.newFileNames = ["xxxx.txt"]; 317 // (Optional) Type of the document to save. The value is in ['Description|File name extensions'] format. To save all files, use 'All files (*.*)|.*'. If there are multiple file name extensions (a maximum of 100 extensions can be filtered), the first one is used by default. If this parameter is not specified, no extension is filtered by default. 318 documentSaveOptions.fileSuffixChoices = ['Document|.txt', '.pdf']; 319 let uri: string = ''; 320 // Obtain the context from the component and ensure that the return value of this.getUIContext().getHostContext() is UIAbilityContext. 321 let context = this.getUIContext().getHostContext() as common.UIAbilityContext; 322 const documentViewPicker = new picker.DocumentViewPicker(context); 323 await documentViewPicker.save(documentSaveOptions).then((documentSaveResult: Array<string>) => { 324 uri = documentSaveResult[0]; 325 console.info('DocumentViewPicker.save to file succeed and uri is:' + uri); 326 }).catch((err: BusinessError) => { 327 console.error(`Invoke documentViewPicker.save failed, code is ${err.code}, message is ${err.message}`); 328 }) 329 if (uri != '') { 330 let config: request.agent.Config = { 331 action: request.agent.Action.DOWNLOAD, 332 url: 'https://xxxx/xxxx.txt', 333 // The saveas field specifies the URI of the file saved by DocumentViewPicker. 334 saveas: uri, 335 gauge: true, 336 // The overwrite field must be set to true. 337 overwrite: true, 338 network: request.agent.Network.WIFI, 339 // The mode field must be set to request.agent.Mode.FOREGROUND. 340 mode: request.agent.Mode.FOREGROUND, 341 }; 342 try { 343 request.agent.create(context, config).then((task: request.agent.Task) => { 344 task.start((err: BusinessError) => { 345 if (err) { 346 console.error(`Failed to start the download task, Code: ${err.code} message: ${err.message}`); 347 return; 348 } 349 }); 350 task.on('progress', async (progress) => { 351 console.warn(`Request download status ${progress.state}, downloaded ${progress.processed}`); 352 }) 353 task.on('completed', async (progress) => { 354 console.warn('Request download completed, ' + JSON.stringify(progress)); 355 // This method requires the user to manage the task lifecycle. After the task is complete, call the remove method to release the task object. 356 request.agent.remove(task.tid); 357 }) 358 }).catch((err: BusinessError) => { 359 console.error(`Failed to operate a download task, Code: ${err.code}, message: ${err.message}`); 360 }); 361 } catch (err) { 362 console.error(`Failed to create a download task, err: ${err}`); 363 } 364 } 365 } catch (err) { 366 console.error(`Failed to create a documentSaveOptions, err: ${err}`); 367 return; 368 } 369 }) 370 } 371 } 372 } 373} 374``` 375 376### Downloading Audios 377 378Call the [save()](../../reference/apis-core-file-kit/js-apis-file-picker.md#save-3) API of [AudioViewPicker](../../reference/apis-core-file-kit/js-apis-file-picker.md#audioviewpicker) to save an audio and obtain the URI of the user file. Use this URI as the value of the **saveas** field of [Config](../../reference/apis-basic-services-kit/js-apis-request.md#config10) to download the audio. 379 380```ts 381import { BusinessError, request } from '@kit.BasicServicesKit'; 382import { picker } from '@kit.CoreFileKit'; 383import { common } from '@kit.AbilityKit'; 384 385@Entry 386@Component 387struct Index { 388 build() { 389 Row() { 390 Column() { 391 Button("Download Audio").width("50%").margin({ top: 20 }).height(40).onClick(async () => { 392 // Create a documentSaveOptions instance. 393 const audioSaveOptions = new picker.AudioSaveOptions(); 394 // (Optional) Name of the file to save. The default value is empty. 395 audioSaveOptions.newFileNames = ['xxxx.mp3']; 396 397 let uri: string = ''; 398 // Obtain the context from the component and ensure that the return value of this.getUIContext().getHostContext() is UIAbilityContext. 399 let context = this.getUIContext().getHostContext() as common.UIAbilityContext; 400 const audioViewPicker = new picker.AudioViewPicker(context); 401 await audioViewPicker.save(audioSaveOptions).then((audioSelectResult: Array<string>) => { 402 uri = audioSelectResult[0]; 403 console.info('AudioViewPicker.save to file succeed and uri is:' + uri); 404 }).catch((err: BusinessError) => { 405 console.error(`Invoke audioViewPicker.save failed, code is ${err.code}, message is ${err.message}`); 406 }) 407 if (uri != '') { 408 let config: request.agent.Config = { 409 action: request.agent.Action.DOWNLOAD, 410 url: 'https://xxxx/xxxx.mp3', 411 // The saveas field specifies the URI of the file saved by AudioViewPicker. 412 saveas: uri, 413 gauge: true, 414 // The overwrite field must be set to true. 415 overwrite: true, 416 network: request.agent.Network.WIFI, 417 // The mode field must be set to request.agent.Mode.FOREGROUND. 418 mode: request.agent.Mode.FOREGROUND, 419 }; 420 try { 421 request.agent.create(context, config).then((task: request.agent.Task) => { 422 task.start((err: BusinessError) => { 423 if (err) { 424 console.error(`Failed to start the download task, Code: ${err.code} message: ${err.message}`); 425 return; 426 } 427 }); 428 task.on('progress', async (progress) => { 429 console.warn(`Request download status ${progress.state}, downloaded ${progress.processed}`); 430 }) 431 task.on('completed', async (progress) => { 432 console.warn('Request download completed, ' + JSON.stringify(progress)); 433 // This method requires the user to manage the task lifecycle. After the task is complete, call the remove method to release the task object. 434 request.agent.remove(task.tid); 435 }) 436 }).catch((err: BusinessError) => { 437 console.error(`Failed to operate a download task, Code: ${err.code}, message: ${err.message}`); 438 }); 439 } catch (err) { 440 console.error(`Failed to create a download task, err: ${err}`); 441 } 442 } 443 }) 444 } 445 } 446 } 447} 448``` 449 450### Downloading Images or Videos 451 452Call the [createAsset()](../../reference/apis-media-library-kit/arkts-apis-photoAccessHelper-PhotoAccessHelper.md#createasset-2) API of [PhotoAccessHelper](../../reference/apis-media-library-kit/arkts-apis-photoAccessHelper.md) to create a media file and obtain the URI of the user file. Use this URI as the value of the **saveas** field of [Config](../../reference/apis-basic-services-kit/js-apis-request.md#config10) to download the media file. 453 454Permission required: [ohos.permission.WRITE_IMAGEVIDEO](../../security/AccessToken/permissions-for-all-user.md#ohospermissionwrite_media) 455 456[ohos.permission.WRITE_IMAGEVIDEO](../../security/AccessToken/permissions-for-all-user.md#ohospermissionwrite_media) is a [restricted permission](../../security/AccessToken/restricted-permissions.md) of the [system_basic](../../security/AccessToken/app-permission-mgmt-overview.md#basic-concepts-in-the-permission-mechanism) level. If the normal-level application needs to request this permission, its APL level must be declared as system_basic or higher. In addition, you should [request the user_grant permission from users](../../security/AccessToken/request-user-authorization.md). 457 458```ts 459import { BusinessError, request } from '@kit.BasicServicesKit'; 460import { photoAccessHelper } from '@kit.MediaLibraryKit'; 461 462import { bundleManager } from '@kit.AbilityKit'; 463import { abilityAccessCtrl, Context, PermissionRequestResult, common } from '@kit.AbilityKit'; 464 465@Entry 466@Component 467struct Index { 468 build() { 469 Row() { 470 Column() { 471 Button("Download Image").width("50%").margin({ top: 20 }).height(40).onClick(async () => { 472 let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION | 473 bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_METADATA; 474 // Obtain accessTokenID of the application. 475 let tokenID = -1; 476 try { 477 await bundleManager.getBundleInfoForSelf(bundleFlags).then((data) => { 478 console.info(`/Request getBundleInfoForSelf successfully. Data: ${JSON.stringify(data)}`); 479 tokenID = data.appInfo.accessTokenId; 480 }).catch((err: BusinessError) => { 481 console.error(`GetBundleInfoForSelf failed. Cause: ${err.message}`); 482 }); 483 } catch (err) { 484 let message = (err as BusinessError).message; 485 console.error('GetBundleInfoForSelf failed: %{public}s', message); 486 } 487 let context: Context = this.getUIContext().getHostContext() as common.UIAbilityContext; 488 489 let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager(); 490 let grant = true; 491 // Check whether the application has the required permission. This API uses a promise to return the result. 492 await atManager.checkAccessToken(tokenID, 'ohos.permission.WRITE_IMAGEVIDEO') 493 .then((data: abilityAccessCtrl.GrantStatus) => { 494 console.log(`/Request checkAccessToken success, data->${JSON.stringify(data)}`); 495 if (data != abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) { 496 grant = false; 497 } 498 }) 499 .catch((err: BusinessError) => { 500 console.error(`CheckAccessToken fail, err->${JSON.stringify(err)}`); 501 }); 502 503 if (!grant) { 504 // Display a dialog box for the user to grant the required permission. This API uses an asynchronous callback to return the result. 505 await atManager.requestPermissionsFromUser(context, ['ohos.permission.WRITE_IMAGEVIDEO']) 506 .then((data: PermissionRequestResult) => { 507 console.info('/Request grant:' + JSON.stringify(data)); 508 console.info('/Request grant permissions:' + data.permissions); 509 console.info('/Request grant authResults:' + data.authResults); 510 console.info('/Request grant dialogShownResults:' + data.dialogShownResults); 511 }).catch((err: BusinessError) => { 512 console.error('Grant error:' + JSON.stringify(err)); 513 }); 514 } 515 516 try { 517 let photoType: photoAccessHelper.PhotoType = photoAccessHelper.PhotoType.IMAGE; 518 let extension: string = 'jpg'; 519 let options: photoAccessHelper.CreateOptions = { 520 title: 'xxxx' 521 } 522 // Obtain a PhotoAccessHelper instance, which can be used for accessing and modifying media files in an album. 523 let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context); 524 // Create an image or video asset with the specified file type, file name extension, and options. This API uses a promise to return the result. 525 let uri: string = await phAccessHelper.createAsset(photoType, extension, options); 526 console.info('/Request createAsset uri' + uri); 527 console.info('/Request createAsset successfully'); 528 529 let config: request.agent.Config = { 530 action: request.agent.Action.DOWNLOAD, 531 url: 'https://xxxx/xxxx.jpg', 532 // The saveas field specifies the URI of the file saved by PhotoAccessHelper. 533 saveas: uri, 534 gauge: true, 535 // The overwrite field must be set to true. 536 overwrite: true, 537 network: request.agent.Network.WIFI, 538 // The mode field must be set to request.agent.Mode.FOREGROUND. 539 mode: request.agent.Mode.FOREGROUND, 540 }; 541 request.agent.create(context, config).then((task: request.agent.Task) => { 542 task.start((err: BusinessError) => { 543 if (err) { 544 console.error(`Failed to start the download task, Code: ${err.code} message: ${err.message}`); 545 return; 546 } 547 }); 548 task.on('progress', async (progress) => { 549 console.warn(`Request download status ${progress.state}, downloaded ${progress.processed}`); 550 }) 551 task.on('completed', async (progress) => { 552 console.warn('Request download completed, ' + JSON.stringify(progress)); 553 // This method requires the user to manage the task lifecycle. After the task is complete, call the remove method to release the task object. 554 request.agent.remove(task.tid); 555 }) 556 }).catch((err: BusinessError) => { 557 console.error(`Failed to operate a download task, Code: ${err.code}, message: ${err.message}`); 558 }); 559 } catch (err) { 560 console.error(`Failed to create a download task, err: ${err}`); 561 } 562 }) 563 } 564 } 565 } 566} 567``` 568 569## Configuring Task Speed Limit and Timeout 570 571You can use the APIs of the [ohos.request](../../reference/apis-basic-services-kit/js-apis-request.md) module to upload local files or download network resource files. To set the task speed limit and duration, the [setMaxSpeed](../../reference/apis-basic-services-kit/js-apis-request.md#setmaxspeed18) API is available since API version 18 and the minimum speed and timeout parameters are available in the [request.agent.create](../../reference/apis-basic-services-kit/js-apis-request.md#requestagentcreate10-1) API since API version 20. 572 573The following sample code shows how to configure the speed and timeout of a download task: 574 575```ts 576// pages/xxx.ets 577// Download the network resource file to the local application file directory, and read data from the file. 578import { common } from '@kit.AbilityKit'; 579import { fileIo } from '@kit.CoreFileKit'; 580import { BusinessError, request } from '@kit.BasicServicesKit'; 581import { buffer } from '@kit.ArkTS'; 582 583@Entry 584@Component 585struct Index { 586 build() { 587 Row() { 588 Column() { 589 Button("Download").onClick(() => { 590 // Obtain the application file path. 591 // Obtain the context from the component and ensure that the return value of this.getUIContext().getHostContext() is UIAbilityContext. 592 let context = this.getUIContext().getHostContext() as common.UIAbilityContext; 593 let filesDir = context.filesDir; 594 595 let config: request.agent.Config = { 596 action: request.agent.Action.DOWNLOAD, 597 url: 'https://xxxx/test.txt', 598 saveas: 'xxxx.txt', 599 gauge: true, 600 overwrite: true, 601 network: request.agent.Network.WIFI, 602 // Rules for setting the minimum speed limit: 603 // 1. If the task speed is lower than the specified value (for example, 16 × 1024 B/s) for a specified period (for example, 10s), the task fails. 604 // 2. Conditions for resetting the timer: 605 // - The speed at any given second is below the minimum speed limit. 606 // - The task is resumed after being paused. 607 // - The task is restarted after being stopped. 608 minSpeed: { 609 speed: 16 * 1024, 610 duration: 10 611 }, 612 // Rules for setting timeout: 613 // 1. connectionTimeout: 614 // - If the time required for establishing a single connection exceeds the specified duration (for example, 60s), the task fails. 615 // - The timer is started independently for each connection (not accumulated). 616 // 2. totalTimeout: 617 // - If the total task duration (including connection and transmission time) exceeds the specified duration (for example, 120s), the task fails. 618 // - The duration is not counted if the task is paused and is accumulated after the task is resumed. 619 // 3. Conditions for resetting the timer: The timer is reset when the task fails or stops. 620 timeout: { 621 connectionTimeout: 60, 622 totalTimeout: 120, 623 } 624 }; 625 request.agent.create(context, config).then((task: request.agent.Task) => { 626 task.start((err: BusinessError) => { 627 if (err) { 628 console.error(`Failed to start the download task, Code: ${err.code} message: ${err.message}`); 629 return; 630 } 631 // Set the maximum task speed. 632 task.setMaxSpeed(10 * 1024 * 1024).then(() => { 633 console.info(`Succeeded in setting the max speed of the task. result: ${task.tid}`); 634 }).catch((err: BusinessError) => { 635 console.error(`Failed to set the max speed of the task. result: ${task.tid}`); 636 }); 637 }); 638 task.on('progress', async (progress) => { 639 console.warn(`/Request download status ${progress.state}, downloaded ${progress.processed}`); 640 }) 641 task.on('completed', async () => { 642 console.warn(`/Request download completed`); 643 let file = fileIo.openSync(filesDir + '/xxxx.txt', fileIo.OpenMode.READ_WRITE); 644 let arrayBuffer = new ArrayBuffer(1024); 645 let readLen = fileIo.readSync(file.fd, arrayBuffer); 646 let buf = buffer.from(arrayBuffer, 0, readLen); 647 console.info(`The content of file: ${buf.toString()}`); 648 fileIo.closeSync(file); 649 request.agent.remove(task.tid); 650 }) 651 }).catch((err: BusinessError) => { 652 console.error(`Failed to create a download task, Code: ${err.code}, message: ${err.message}`); 653 }); 654 }) 655 } 656 } 657 } 658} 659``` 660 661## Adding Network Configuration 662 663### Intercepting HTTP 664 665You can set the configuration file to intercept HTTP. After HTTP is disabled for the **ohos.request** module, upload and download tasks using plaintext HTTP cannot be created. The configuration file is stored in the **src/main/resources/base/profile/network_config.json** directory of the application. For details, see the parameters in the [configuration file](../../reference/apis-network-kit/js-apis-net-connection.md#connectionsetapphttpproxy11) of the network management module. 666 667The sample configuration file is as follows: 668 669```ts 670{ 671 "network-security-config": { 672 "base-config": { 673 "cleartextTrafficPermitted": true, 674 "trust-anchors": [ 675 { 676 "certificates": "/etc/security/certificates" 677 } 678 ] 679 }, 680 "domain-config": [ 681 { 682 "cleartextTrafficPermitted": true, 683 "domains": [ 684 { 685 "include-subdomains": true, 686 "name": "*.example.com" 687 } 688 ], 689 } 690 ] 691 } 692} 693``` 694