/ cordova

Writing binary file in Cordova and uploading it to server using Cordova File Transfer plugin

Cordova File Transfer plugin allows you to transfer / upload photos from mobile to server. You generally need a file with path for transferring / uploading files via File Transfer plugin.

More information on how to use Cordova File transfer plugin can be found here.

This plugin won't help much when we have a Base64 image (usually a drawing or signature drawn on canvas). To upload such images we can do:

  1. take your base64.
  2. write it to a file.
  3. then just use file transfer plugin to upload it to server.

In this article, I would explain how we can write Base64 image to a file using Javascript.

  • First, we would need to convert Base64 image to file-like object (blob).
    • For this we would make use of atob() javascript function which decodes a string of data which has been encoded using base-64 encoding.
    • Next we would convert the decoded base-64 string to an array of 8-bit unsigned integers using Uint8Array()function.
    • Array of unsigned 8-bit integers is converted to Blob by using the Blob() constructor.

Following is the JS code sample that would convert Base64 to Blob:

    function base64toBlob(b64Data, contentType, sliceSize) {
      var blob, byteArray, byteArrays, byteCharacters, byteNumbers, i, offset, slice;
      contentType = contentType || '';
      sliceSize = sliceSize || 512;
      byteCharacters = atob(b64Data);
      byteArrays = [];
      offset = 0;
      while (offset < byteCharacters.length) {
        slice = byteCharacters.slice(offset, offset + sliceSize);
        byteNumbers = new Array(slice.length);
        i = 0;
        while (i < slice.length) {
          byteNumbers[i] = slice.charCodeAt(i);
          i++;
        }
        byteArray = new Uint8Array(byteNumbers);
        byteArrays.push(byteArray);
        offset += sliceSize;
      }
      blob = new Blob(byteArrays, { type: contentType });
      return blob;
    }
  • Next, we would write this blob to temporary storage of the cordova app. For this we would initialize temporary filesystem.

     document.addEventListener('deviceready',function(){
       window.requestFileSystem(window.TEMPORARY, 5 * 1024 * 1024, (function(fs) {
         var dirEntry, fileName;
         console.log('file system open: ' + fs.name);
         fileName = 'signature.png';
         dirEntry = fs.root;
         return dirEntry.getFile(fileName, {
           create: true,
           exclusive: false
         }, (function(fileEntry) {
           return writeFile(fileEntry); // writeFile is a method that would write blob into initialized temp storage.
         }), fail);
       }), fail);
     }, false);
    
     function fail(e) {
       console.log('Error : ', e.code);
     }
    
  • Now we write writeFile method that would write blob into initialized temp storage.

     function writeFile(fileEntry) {
       base64 = canvasObject.toDataURL("image/png"); // Base64 string
       
       fileEntry.createWriter(function(fileWriter) {
         var data, string, type;
         string = base64.split(';base64,');
         type = string[0].split(':')[1];
         data = base64toBlob(string[1], type);
         
         fileWriter.onwriteend = function() {
           console.log('Successful file write...');
           
           // Call function that would upload file via File Transfer plugin.
           // Example: upload(fileEntry)
         };
    
         fileWriter.onerror = function(e) {
           return console.log('Failed file write: ' + e.toString());
         };
         
         return fileWriter.write(data);
       });
     });
    

In onwriteend callback, we can call FileTransfer plugin to upload the file to server.