title: How to download and save a file using phonegap/cordova on Android
body: <p>I am at my whit's end.
  I will try to keep it brief.
  Using Cordova/Phonegap 3.0 (and get the same results on 2.8.0). 
  Android version 4.0.4.
  Code works on BlackBerry10 (Q10 and Z10).</p>
  
  <p>On Android it errors with a JSON Error (no, I'm not parsing JSON, this seems to come out of cordova's bowels). I will paste the JSON.stringified error object at the end of this.</p>
  
  <p>So, on to code then:
  First a filesystem success function:</p>
  
  <pre><code>function onFSSuccess(fileSystem) {
  if (fileSystem == null) {
      window.alert("fileSystem is null");
  }
  var root = fileSystem.root; 
  root.getDirectory("com.app.id",{create:true},gotDir,onError);};
  </code></pre>
  
  <p>Then a function to handle success with directory retrieval:</p>
  
  <pre><code>function gotDir(d){
      DATADIR = d;        
      doTheDl (d.fullPath + "/update.sql",fileTransfer);
  };
  </code></pre>
  
  <p>Then the actual call to get the filesystem:</p>
  
  <pre><code>window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, onFSSuccess, null);
  </code></pre>
  
  <p>Then a function to download the file:</p>
  
  <pre><code>function doTheDl (localPath,fileTransfer) {
      try {
          window.alert ("Downloading to '" + localPath + "'");
          fileTransfer.download (
              uri,
              localPath,
              function (entry) {
                  try {
                      $("#dbDownloadProgressContainer").text("File saved to " + entry.name + ". Applying script to database...");
                      dbInitObj.applyUpdateScript(entry); 
                  }
                  catch (e) {
                      window.alert ( e);
                  }
  
              },
              function (err) {
                  window.alert ("ERROROR!!! - " + err);
                  var errCodeName = err.code;
                  switch (err.code) {
                      case FileTransferError.FILE_NOT_FOUND_ERR:
                          errCodeName ='FILE_NOT_FOUND_ERR';
                          break;
                      case FileTransferError.INVALID_URL_ERR:
                          errCodeName="INVALID_URL_ERR";
                          break;
                      case FileTransferError.CONNECTION_ERR:
                          errCodeName="CONNECTION_ERR";
                          break;
                      case FileTransferError.ABORT_ERR:
                          errCodeName="ABORT_ERR";
                          break;
                      default:
                          errCodeName = "UNKNOWN";
                          break;                      
                  }
                  window.alert ("Download failed: " + err.source + ", " + err.target + ", " + errCodeName);
              },
              true                
          );
  
      }
      catch (e) {
          window.alert ( e);
      }
  }
  </code></pre>
  
  <p>Man, gotta love all these async callbacks...
  Next we get to the heart of the matter, trying to READ the downloaded file:</p>
  
  <pre><code>//Bulk of applyUpdateScript script ommited, but eventually it gets here:
  
  function readComplete (evt) {
  
      $("#dbDownloadProgressContainer").text("Parsing script file...");
  
      //Got this gem from here: http://beckism.com/2010/09/splitting-lines-javascript/
      var lines = evt.target.result.match(/^.*([\n\r]+|$)/gm);
  
  
      //var lineIndx = lines.length;
  
      window.setTimeout(function () {
              $("#dbDownloadProgressContainer").text("Processing " + lines.length + " statements");
  },50);
  };  
  
  try {
          var fileReader = new FileReader();
          fileReader.onloadend=readComplete;
  
          fileReader.onerror=function (err) {
              //var errStr = translateFileError (err);
              window.alert ("FileReader.onerror: " +JSON.stringify (err));
          };
  
  
          fileReader.onloadstart=function (evt) {
              window.alert ("FileReader.onloadstart - " + JSON.stringify (evt));
          };
  
  
          fileReader.onload=function (evt)
          {
              window.alert ("FileReader.onload - Called when the read has successfully completed.- " + JSON.stringify (evt));
          };
  
  
          fileReader.onprogress = function (evt)
          {
              window.alert ("FileReader.onprogress - " + JSON.stringify (evt));
          }
  
          fileReader.onabort = function (evt)
          {
              window.alert ("FileReader.onabort - " + JSON.stringify (evt));
          }
  
  
          function gotFile (fileEntry) {
              window.alert ("Activating reader for file '" + fileEntry.fullPath + "'");
              fileReader.readAsText(fileEntry);
  
          };
  
          function noFileFound (fileError) {
              alert ("Can not access database update script: code " + translateFileError (fileError));
          };
  
          // window.alert ("scriptPath.name = " + scriptPath.name);
  
          DATADIR.getFile (scriptPath.name,null,gotFile,noFileFound);
      }
      catch (e) {
          window.alert (e);
  }
  </code></pre>
  
  <p>NOW, when I hit the reading bits, I eventually get this from the 'onerror' event (rember this is the JSON.stringfied error object:</p>
  
  <pre><code>{
     "type":"error",
     "bubbles":false,
     "cancelBubble":false,
     "cancelable":false,
     "lengthComputable":false,
     "loaded":0,
     "total":0,
     "target":{
        "_readyState":2,
        "_error":{
           "code":"JSON error"
        },
        "_result":null,
        "_fileName":"file:///mnt/sdcard/com.app.id/update.sql",
        "_realReader":{
           "error":null,
           "result":"",
           "readyState":0
        }
     }
  }
  </code></pre>
  
  <p>Please also note that 'com.app.id' is a place holder for the actual app ID - can't paste that for fear of sensitive names. I did try other folder names as well.
  Other notable(?) items:</p>
  
  <ul>
  <li>The download progress event seems to indicate that we are downloading precisely double the actual file size (wtf?)</li>
  <li>Results are the same on android device and emulator</li>
  <li>BlackBerry10 seems to work fine</li>
  </ul>
  
  <p>Thanks in advance to any clever people....</p>