Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Hosted-services / Cordova

PDF Viewer with Cordova and AngularJS

4.94/5 (7 votes)
30 Jul 2015CPOL3 min read 51.1K   1.3K  
An Apache Cordova app that can download a PDF from an URL, store the PDF in the device and show the PDF to the user

Introduction

The other day I needed to download a PDF into a device and show it. I thought about an Apache Cordova project. To accomplish this, I made a little example app with Apache Cordova and AngularJS. This app can download a PDF from a URL, store it and show it to the user.

Source Code

The source code accompanying this article can be found on Github.

Plugins

The app requires plugins to work. The following list show the plugins needed and his utility.

  • InAppBrowser - It allows opening new navigator’s window and even opening the system navigator opening.
  • File - Access to files paths
  • FileTransfer - Download
  • Device - It allows you to see information of the platform in which the app is running.

NOTE: You may need the Whitelist plugin.

Plugins work on Windows Phone and Windows 8, however, I haven't tried to run it on Windows Phone and Windows 8 in this example.

Platform Singularities

In this development came into play some peculiarities of each platform. Therefore, creating one source code for every platform is complicated.

Android

  • It CAN’T open a new navigator’s window into the same app to show PDFs
  • It CAN open system navigator. Also the system ALLOWS CHOOSING the app that will open the file.
  • It has SOME SHARED DIRECTORIES

iOS

  • It CAN open a new navigator’s window into the same app to show PDFs
  • It CAN open system navigator. However the system DOESN'T ALLOW CHOOSING the app that will open the file and show the file into the navigator system.
  • It has ONLY PRIVATE DIRECTORIES.

Solution

Android: PDF file will be downloaded and stored into a shared directory and it will be opened by the system. You need to store it in a shared directory so that other apps can get access to it.

iOS: PDF file will be opened into a new navigator’s windows into the example app. You need to open a window into the app because on iOS you can’t share files with others apps.

In a nutshell, only two parameters should be dependents on the platform: file path and how to open a file.

In the File Plugin documentation, you can find tables that indicate which paths are read/write or which paths are privates. Click here.

Using the Code

The main functionality is split in two AngularJS services. The first is a download service to download and save a file from an URL. The other one shows a file from an URI, this service can show files from an URL or from a local storage system.

Download Service

For the example, the service was declared like a factory and the first thing to do is to decide where to store files. For that, we use the "deviceready" event to know when the plugins will be available.

This service use data directory for iOS and the external application storage directory for Android.

JavaScript
//
// Any source code blocks look like this
//
angular.module("pdfViewer.download").factory('downloadService', ['$document', 
	function ($document) {
		var _saveDirectory = "";
		var _fileTransfer;
		
		$document[0].addEventListener("deviceready", function () {
			_fileTransfer = new FileTransfer();
			if (device.platform === "iOS") {
				_saveDirectory = cordova.file.dataDirectory;
			}
			else if (device.platform === "Android") {
				_saveDirectory = cordova.file.externalApplicationStorageDirectory;
			}
			else {
				_saveDirectory = cordova.file.dataDirectory;
			}

		}, false);

		return {};
	}]);

Now, the service needs to expose a method that implements the download function. The download function creates a directory called "PDF" into the storage directory, then download the file by URL parameter.

Download function returns the file path in a promise.

JavaScript
angular.module("pdfViewer.download").factory('downloadService', ['$document', '$q',
	function ($document, $q) {
		var _saveDirectory = "";
		var _fileTransfer;
		// Set attributes from Cordova plugins
		$document[0].addEventListener("deviceready", function () {
			_fileTransfer = new FileTransfer();
			if (device.platform === "iOS") {
				_saveDirectory = cordova.file.dataDirectory;
			}
			else if (device.platform === "Android") {
				_saveDirectory = cordova.file.externalApplicationStorageDirectory;
			}
			else {
				_saveDirectory = cordova.file.dataDirectory;
			}

		}, false);

		return {
			download: function (url, fileName) {
				return $q(function (resolve, reject) {
					window.resolveLocalFileSystemURL
					(_saveDirectory ,  function (dir) {
						dir.getDirectory("PDF", 
						{ create: true }, function (finalDir) {
						   
							if (!_fileTransfer) {
								reject('error.noTransfer');
							}
							if (!_saveDirectory) {
								reject('error.noDirectory');
							}
							
							var fileURL = _saveDirectory + fileName;
							var uri = encodeURI(url);
							_fileTransfer.download(
								uri,
								fileURL,
								function (entry) {
									resolve(entry.toURL());
								},
								function (error) {
									reject(error);
								},
								true
							);
						});
						
					});
				});
			}
		}
	}]);

Viewer Service

Same as before, the service was declared like a factory and the first thing to do is specify the platform dependant parameter. Then, the service exposes the open function.

JavaScript
angular.module("pdfViewer.viewer").factory('viewerService', 
['$document', '$window', function ($document, $window) {
	var _type = "";
	var _open;
	$document[0].addEventListener("deviceready", function () {
		_open = $window.open;
		if (device.platform === "iOS") {
			_type = "_blank";
		}
		else if (device.platform === "Android") {
			_type = "_system";
		}
		else {
			_type = "_system";
		}

	}, false);
	return {
		showPDF: function (fileToShow) {
			_open(encodeURI(fileToShow),_type,'location=no')
		}
	}
}]);

In the source code, you can see an example controller and view for downloading and showing a PDF with this service.

Points of Interest

I need download, store and show a PDF. However, you can use these services for download, store and show other file types (like docx).

I made this example using Visual Studio 2015 and his Apache Cordova Tools. I'm working to improve the code.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)