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 = "";

//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");, store + fileName, 
		function(entry) {
		function(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:

  • 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.

  • Prashant

    In my case, i will be download file depending on productid. So i dont know what will be the file name and its extension. So how can i download this file.?
    For eg:
    Will give ABC.doc
    Will give Five.pdf
    Will give Five.xls
    So how can i specify my filename?

    • http://www.raymondcamdencom/ Raymond Camden

      You would need to modify your API to return the name. For example, I’d have an API that returns the file name and the “download.php” url. You would then make a second request to get the binary data.

  • Дадыкин Павел

    Hello! Thanks for your post.
    But I have a question. How to delete files?
    In my app I have to download zip file to cordova.file.dataDirectory, and extract it to cordova.file.dataDirectory/folder.
    But when file updates on the server, I need to download new zip file and delete old zip file and all files stored in cordova.file.dataDirectory/folder.

    Please, tell me, how to delete these files.
    Thank you!

  • Alessandro Belli

    is it possibile to make a loop for check more files?

    • http://www.raymondcamdencom/ Raymond Camden


  • Jay J. Das

    Hello! Raymond

    Can we download the file to the downloads folder?
    What should be the path for store, instead of



    • http://www.raymondcamdencom/ Raymond Camden

      I don’t know. I checked the File plugin ( and there is no alias for it, but obviously if you know the full path to the downloads folder, and it is writeable by your app, then it is a simple matter.

      • Karthikeya Mishra

        I have used cordova.file.externalRootDirectory to create a folder. And I downloaded the photos in that folder. But now my problem is I want to check whether the file I am downloading already exist in that folder but I am unable to get the path of that folder.

        I am using Ionic framewrok. To download the image in folder I used –

        $scope.downloaad= function(photoUrl, photoId, folder){
        var url = photoUrl;
        var targetPath = cordova.file.externalRootDirectory+”/”+folder+”/”+options.photoId+”.jpg”;

        var trustHosts = true;
        var str = {};

        $, targetPath, str, trustHosts)
        .then(function(result) {
        console.log(“result->” + result);
        }, function(err) {
        console.log(“error->” + err);


        • http://www.raymondcamdencom/ Raymond Camden

          Are you saying you want to resolve the path to a DirectoryEntry object you can work with?

  • mralj

    Hey, thanks for the great article. I’ve tried to implement your code in my app, which has to do this: check if video exists, if it does play it, else download it and play it. But it doesn’t work, problem is both every time success and fail functions get called. So if video exists app plays it, but it also downloads it again. Here is relevant part of my code:

    var store = cordova.file.dataDirectory;
    var filePath = store + “videoTest.mp4”;

    //Check for the file.
    window.resolveLocalFileSystemURL(filePath, playVideo(filePath, true), transferFile(uri, filePath));

    Also here is my SO question with a bit different code, but same problem:

    Please, if it is not too much trouble, could you tell me what am I doing wrong ?

    Thanks in advance !

    • http://www.raymondcamdencom/ Raymond Camden

      I posted an answer there.

      • mralj

        Hey, thanks for the fast response :)

  • tomiwaadefokun

    Thanks for the great post. But how do I open the file via a link?

    • http://www.raymondcamdencom/ Raymond Camden

      Just link to it? :)

  • tomiwaadefokun

    Many thanks. Using url = entry.toURL() gives me file:///path/to/file and it doesn’t open in browser and not even in inAppBrowser. Both, ‘_system’) and, ‘_blank’) did not work.

    • http://www.raymondcamdencom/ Raymond Camden

      What happens though? You said it didn’t work- did it throw an error? What did remote debugging show you?

      • tomiwaadefokun

        I get “Options expected to be an object”, from inAppBrowser. I have no idea what that means…

        • http://www.raymondcamdencom/ Raymond Camden

          Double check to ensure you are running this plugin –

          • tomiwaadefokun

            The problem is ngCordova’s InAppBrowser implementation actually requires the options to be passed as object. Now the file opens with a PDF reader but it says “Document path is not valid.” Please what can be the issue? Many thanks for your time.

          • http://www.raymondcamdencom/ Raymond Camden

            Was the file downloaded to a temporary location?

          • tomiwaadefokun

            The file was downloaded to cordova.file.dataDirectory directly, I am suspecting it may be that it is private. Could that be the case?

          • tomiwaadefokun

            I changed the path to cordova.file.externalApplicationStorageDirectory and it worked well. How reliable is this path?

          • http://www.raymondcamdencom/ Raymond Camden

            I’d check what the FIle plugin doc has to say about it.

          • tomiwaadefokun

            Many thanks Raymond, I really appreciate.