This post discusses how to download files to your device from your API in an Ionic 3 application. By using the File and File Transfer plugins that are available for Ionic you can accomplish this task.First, you install the necessary plugins — File and File Transfer. You can refer to Ionic’s documentation here to install them.
- https://ionicframework.com/docs/v3/native/file/
- https://ionicframework.com/docs/v3/native/file-transfer/
Make certain that you add the plugins to your providers in the main app module. Next, you create a service to handle the download. Using a service takes advantage of Angular’s modularity and reusability. Remember to add the following service to your providers in the main app module.
1import { Injectable } from "@angular/core";
2import { Observable } from "rxjs/Observable";
3import { fromPromise } from "rxjs/observable/fromPromise";
4import { FileTransfer, FileTransferObject } from '@ionic-native/file-transfer';
5import { Platform, AlertController } from "ionic-angular";
6import { File } from "@ionic-native/file";
7import { AndroidPermissions } from '@ionic-native/android-permissions';
8
9@Injectable()
10export class DownloadService {
11 constructor(
12 private transfer: FileTransfer,
13 private file: File,
14 private platform: Platform,
15 private androidPermissions: AndroidPermissions,
16 private alertCtrl: AlertController
17 ) {
18 }
19
20 public downloadFile(fileId: number, fileName: string): Observable<any> {
21 return fromPromise(this.performDownload(fileId, fileName, fileExtension));
22 }
23
24 protected async performDownload(fileId: number, fileName: string){
25 // We added this check since this is only intended to work on devices and emulators
26 if (!this.platform.is('cordova')) {
27 console.warn('Cannot download in local environment!');
28 return;
29 }
30
31 const fileTransfer: FileTransferObject = this.transfer.create();
32
33 let uri = encodeURI(`www.yourapi.com/file/download?id=fileId`);
34
35 let path = await this.getDownloadPath();
36
37 let fullFileName = fileName + '.' + fileExtension;
38
39 // Depending on your needs, you might want to use some form of authentication for your API endpoints
40 // In this case, we are using bearer tokens
41 let bearerToken = 'yourToken';
42
43 return fileTransfer.download(
44 uri,
45 path + fileName,
46 false,
47 {
48 headers: {
49 "Authorization": `Bearer ${bearerToken}`
50 }
51 }
52 ).then(
53 result => {
54 this.showAlert(true, fileName);
55 },
56 error => {
57 this.showAlert(false, fileName);
58 }
59 )
60 }
61
62 public async getDownloadPath() {
63 if (this.platform.is('ios')) {
64 return this.file.documentsDirectory;
65 }
66
67 // To be able to save files on Android, we first need to ask the user for permission.
68 // We do not let the download proceed until they grant access
69 await this.androidPermissions.checkPermission(this.androidPermissions.PERMISSION.WRITE_EXTERNAL_STORAGE).then(
70 result => {
71 if (!result.hasPermission) {
72 return this.androidPermissions.requestPermission(this.androidPermissions.PERMISSION.WRITE_EXTERNAL_STORAGE);
73 }
74 }
75 );
76
77 return this.file.externalRootDirectory + "/Download/";
78 }
79
80 // Here we are using simple alerts to show the user if the download was successful or not
81 public showAlert(hasPassed: boolean, fileName: string) {
82 let title = hasPassed ? "Download complete!" : "Download failed!";
83
84 let subTitle = hasPassed ? `Successfully downloaded ${fileName}.` : `There was a problem while downloading ${fileName}`;
85
86 const alert = this.alertCtrl.create({
87 title: title,
88 subTitle: subTitle,
89 buttons: ['OK']
90 });
91 alert.present();
92 }
93}
94
Next, you inject the download service into the page and add a function to be called from your template. That code looks as follows:
1import { Component} from '@angular/core';
2import { IonicPage, NavController } from 'ionic-angular';
3import { DownloadService } from '../../providers/download/download-service';
4
5@IonicPage()
6@Component({
7 selector: 'page-downloads',
8 templateUrl: 'downloads.html',
9})
10export class DownloadsPage {
11
12 // Here we are injecting our download service into our page
13 constructor(private downloadService: DownloadService{ }
14
15 // This is the function that will trigger the download
16 public downloadFile(fileId: number, fileName: string) {
17 this.downloadService.downloadFile(fileId, fileName).subscribe();
18 }
19
20}
Finally, add the necessary code to call the function from page template. The assumption is that you have a list of items to be downloaded.
1<ion-list>
2 <ng-container *ngFor="let item of downloadableItems">
3 <button (click)="downloadFile(item.id, item.name)">
4 <div>
5 <h2>{{ content.name }}</h2>
6 </div>
7 </button>
8 </ng-container>
9</ion-list>
In summary, you create a service to handle the download. Then, you inject the service into the page and add a function to be called from the template. Finally, you call the function. Now, you can successfully download files from an API to your device.
Accelerate Your Career with 2am.tech
Join our team and collaborate with top tech professionals on cutting-edge projects, shaping the future of software development with your creativity and expertise.
Open Positions