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}
94Next, 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.



