Cordova Sample: Check for a file and download if it isn’t there

I’ve begun work on trying to answer the questions I gathered concerning Cordova’s FileSystem support. As I work through the questions I’m trying to build “real” samples to go along with the text. My first sample is a simple one, but I think it is pretty relevant for the types of things folks may do with Cordova and the file system – checking to see if a file exists locally and if not – fetching it.

I’ll begin by sharing the code and then explaining the parts. Here is the entire JavaScript file for the application. (Earlier today, Andrew Grieve shared a way my code could be simplified by a good 1/3rd. The code below reflects his update and has been changed since my original writing of the blog post.)

document.addEventListener("deviceready", init, false);

//The directory to store data
var store;

//Used for status updates
var $status;

//URL of our asset
var assetURL = "https://raw.githubusercontent.com/cfjedimaster/Cordova-Examples/master/readme.md";

//File name of our important data file we didn't ship with the app
var fileName = "mydatafile.txt";

function init() {
	
	$status = document.querySelector("#status");

	$status.innerHTML = "Checking for data file.";

	store = cordova.file.dataDirectory;

	//Check for the file. 
	window.resolveLocalFileSystemURL(store + fileName, appStart, downloadAsset);

}

function downloadAsset() {
	var fileTransfer = new FileTransfer();
	console.log("About to start transfer");
	fileTransfer.download(assetURL, store + fileName, 
		function(entry) {
			console.log("Success!");
			appStart();
		}, 
		function(err) {
			console.log("Error");
			console.dir(err);
		});
}

//I'm only called when the file exists or has been downloaded.
function appStart() {
	$status.innerHTML = "App ready!";
}

Ok, let’s break it down. The first step is to check to see if our file exists already. The question is – where should we store the file? If you look at the docs for the FileSystem, you will see that the latest version of the plugin adds some useful aliases for common folders. Unfortunately, the docs are not exactly clear about how some of these aliases work. I asked for help (both on the PhoneGap Google group and the Cordova development list) and got some good responses from Kerri Shotts and Julio Sanchez.

The directory that I thought made sense, cordova.file.applicationStorageDirectory, is incorrectly documented as being writeable in iOS. A pull request has already been filed to fix this mistake. For my application, the most appropriate directory is the next one, cordova.file.dataDirectory. Once I have my directory alias, I can make use of resolveLocalFileSystem on the directory plus desired file name to see if it exists. The third argument, downloadAsset, will only be run on an error, in this case a file not existing.

If the file does not exist, we then have to download it. For this we use a second plugin, FileTransfer. This is where one more point of confusion comes in. We need to convert that earlier DirectoryEntry object, the one we used to get an API for files and directories, back to a URL so we can give a path to the Download API.

So to recap – we’ve got a few moving parts here. We’ve got a directory alias, built into the plugin for easily finding common folders for our application. Again, the docs here are currently a bit wrong but they should be corrected soon. From that we can quickly see if our desired file exists, and if not, use the FileTransfer plugin to download it.

Simple… but even a simple application caused me a bit of trouble, so hopefully this helps others. You can get the full source code here: https://github.com/cfjedimaster/Cordova-Examples/tree/master/checkanddownload

  • rajesh rs

    Hi Raymond, thanks for the post.

    i was trying the upload plugin for uploading a “zip” file to the server.

    the zip file successfully uploads to the server but the web service does some operation based on the uploaded zip file before returning success. But on the device side i get an cordova error as below:

    “File Transfer Error: The request timed out.” code : 3

    please let me know how to handle this or is there a way to increase the timeout for this plugin ?

    • http://www.raymondcamdencom/ Raymond Camden

      I’m not seeing an option for that. I’d file a bug report.