12
Dec

Ionic – Downloading a file with ngCordova’s $cordovaFile.

Recently we decided to build an Android podcast app using the Ionic framework and ngCordova. ngCordova is an angularJs wrapper for Apache Cordova plugins, which in theory, should make them nice and easy to use within your angular/cordova apps. Here’s the link to ngCordova: http://ngcordova.com/docs/

Unfortunately the documentation is rather scant, and solutions to most of the issues we were encountering were absent from Google, so we thought we’d document the process here. We found that many people were having similar problems to us (on the Ionic forums/StackOverflow), so hopefully this should help you guys out.

 

Let’s Start…

To make things simple we’ll start from the beginning and create a fresh Ionic Framework project through terminal/Git Bash (Linux/Windows)

ionic start IonicProject blank
cd IonicProject
ionic platform add android

Here you’ve created a fresh Ionic project, gone into the newly created Ionic app directory, and added the ability to build for the Android platform.

Next, follow the steps to install ngCordova.

Add the plugins…

In the same terminal/git bash add both ngCordova $cordovaFile plugins:

cordova plugin add org.apache.cordova.file
cordova plugin add org.apache.cordova.file-transfer

Download the file…

Looking at the we have a couple of fairly obvious functions that must be called in order to be able to download the file to your device: $cordovaFile.createDir() & $cordovaFile.downloadFile(). Where createDir() will create a directory on your device for the file to be saved to, and downloadFile() will download the file into that directory. However, that isn’t quite how it works. The other necessary function that wasn’t obvious to us, at first, is $cordovaFile.createFile(). createFile() is actually used to create the file in the directory, and downloadFile() downloads the file to THAT created file. Using createFile() beforehand makes it easier to get the URL to the file location you wish to download to. It’s a little counter-intuitive, but does make sense.

This will work with any type of file, but since we were building a podcast app, we used a podcast from the Freedomain Radio philosophy show.

As with all plugins, we had to inject $cordovaFile as a dependency into our controller. Here is the controller code:

exampleApp.controller('ExampleController', function($scope, $ionicPlatform, $cordovaFile) {
  var directory = 'downloads';
  var filename = 'download.mp3';

  $ionicPlatform.ready(function() {})
  .then(function() {
    return $cordovaFile.createDir(directory, false);
  })
  .then(function() {
    return $cordovaFile.createFile(directory + '/' + filename, false);
  })
  .then(function(newFile) {
    return $cordovaFile.downloadFile(url, newFile.nativeURL);
  })
  .then(function(result) {
    // Success!
  }, function(err) {
    // Error
  }, function (progress) {
    // constant progress updates
    console.log('Downloading: '+(progress.loaded/progress.total).toFixed()+'%');
  });
});

Voila! File download to a device: successful.

In the podcast app we built, we moved this functionality into a Downloads service, and used the Angular event broadcasting mechanism to support background downloading, report download progress updates to controllers and also to support multiple simultaneous downloads.

To see how we achieved this, please check out our progress bar blog post.