5

On Android, I'm trying to upload the output from Cordova/Phonegap getPicture() using Google Drive API: Insert File. Is there a way to do this using the FILE_URI instead of DATA_URL (base64)?

I tried Camera.DestinationType.DATA_URL first, but it didn't return Base64 data like it was supposed to, it just returned the same thing as FILE_URI. So now I'm trying to figure out how to pass FILE_URI to Google Drive Insert File (which takes Base64). Is there a way to convert FILE_URI to Base64?

Cordova code:

navigator.camera.getPicture(onSuccess, onFail,
    { quality: 50, destinationType: Camera.DestinationType.FILE_URI });

function onSuccess(imageURI) {
    var image = document.getElementById('myImage');
    image.src = imageURI;

    // need to do something like this:
    var fileData = ConvertToBase64(imageURI);
    insertFile(fileData);
}

Google Drive code:

/**
 * Insert new file.
 *
 * @param {File} fileData File object to read data from.
 * @param {Function} callback Function to call when the request is complete.
 */
function insertFile(fileData, callback) {
  const boundary = '-------314159265358979323846';
  const delimiter = "\r\n--" + boundary + "\r\n";
  const close_delim = "\r\n--" + boundary + "--";

  var reader = new FileReader();
  reader.readAsBinaryString(fileData);
  reader.onload = function(e) {
    var contentType = fileData.type || 'application/octet-stream';
    var metadata = {
      'title': fileData.fileName,
      'mimeType': contentType
    };

    var base64Data = btoa(reader.result);
    var multipartRequestBody =
        delimiter +
        'Content-Type: application/json\r\n\r\n' +
        JSON.stringify(metadata) +
        delimiter +
        'Content-Type: ' + contentType + '\r\n' +
        'Content-Transfer-Encoding: base64\r\n' +
        '\r\n' +
        base64Data +
        close_delim;

    var request = gapi.client.request({
        'path': '/upload/drive/v2/files',
        'method': 'POST',
        'params': {'uploadType': 'multipart'},
        'headers': {
          'Content-Type': 'multipart/mixed; boundary="' + boundary + '"'
        },
        'body': multipartRequestBody});
    if (!callback) {
      callback = function(file) {
        console.log(file)
      };
    }
    request.execute(callback);
  }
}
wisbucky
  • 33,218
  • 10
  • 150
  • 101

3 Answers3

3

I realize this is a bit old - but it now looks like you can use a FileReader in phoneGap.

I haven't tested this yet, but something like this should also work, without the canvas hack.

[EDIT - tested and revised the code below. works for me :D ]

var cfn = function(x) { console.log(x) };
var cameraOps = { quality: 50, destinationType: Camera.DestinationType.FILE_URI };
navigator.camera.getPicture(function(imagePath) {
    window.resolveLocalFileSystemURL(imagePath, function(fileEntry) {
        fileEntry.file(function (file) {
            var reader = new FileReader();
            reader.onloadend = function(evt) {
                console.log("read success!!!");
                console.log(evt.target.result);
            };
            reader.readAsDataURL(file);
        }, cfn);
    }, cfn);
}, cfn);
jvperrin
  • 3,368
  • 1
  • 23
  • 33
nihlton
  • 659
  • 6
  • 7
2

Yes you can....

Specify Destination Type as FILE_URI itself and in imagedata you will be getting the images file uri place it in a image tag and then place it inside HTML5 canvas and canvas has one method called toDataURL where you will be able to get the base64 of the corresponding image.

function onSuccess(imageData)
     {

                var $img = $('<img/>');
                $img.attr('src', imageData);
                $img.css({position: 'absolute', left: '0px', top: '-999999em', maxWidth: 'none', width: 'auto', height: 'auto'});
                $img.bind('load', function() 
                {
                    var canvas = document.createElement("canvas");
                    canvas.width = $img.width();
                    canvas.height = $img.height();
                    var ctx = canvas.getContext('2d');
                    ctx.drawImage($img[0], 0, 0);
                    var dataUri = canvas.toDataURL('image/png');

                });
                $img.bind('error', function() 
                {
                    console.log('Couldnt convert photo to data URI');
                });

    }
Arun Bertil
  • 4,598
  • 4
  • 33
  • 59
  • hmm, that's interesting. I have a couple questions. 1) Is the output of canvas.toDataURL resampling my original jpeg? Or is it identical? 2) I guess this would only work for images, and not other types of files? – wisbucky Sep 18 '13 at 09:02
  • 1)Yes...you will get the base64 of the original image...both are identical...no problems..2)I have tried it for images only and it works..I dont think it will work for other file types.. – Arun Bertil Sep 18 '13 at 09:05
  • 1
    Alterantive approach is use File Transfer API of Phonegap http://docs.phonegap.com/en/1.0.0/phonegap_file_file.md.html#FileTransfer – Arun Bertil Sep 18 '13 at 09:32
  • 1
    Thanks Arun. I somehow couldn't get your example to run. But it put me on the right path, and I was able to get it to work! See http://stackoverflow.com/a/18881640/1081043 – wisbucky Sep 18 '13 at 20:22
  • _"1)Yes...you will get the base64 of the original image...both are identical...no problems"_ I believe that technically, it is re-encoding the image. It wouldn't make any difference if original and output are both PNG (lossless), but if the output is image/jpeg, there will be re-encoding loss. – wisbucky Sep 19 '13 at 16:50
2

Thanks to Arun for pointing me in the right direction. I ended up using this javascript function, which was based off http://jsfiddle.net/jasdeepkhalsa/L5HmW/

function getBase64Image(imgElem) {
// imgElem must be on the same server otherwise a cross-origin error will be thrown "SECURITY_ERR: DOM Exception 18"
    var canvas = document.createElement("canvas");
    canvas.width = imgElem.clientWidth;
    canvas.height = imgElem.clientHeight;
    var ctx = canvas.getContext("2d");
    ctx.drawImage(imgElem, 0, 0);
    var dataURL = canvas.toDataURL("image/jpeg");
    dataURL = dataURL.replace(/^data:image\/(png|jpg|jpeg);base64,/, "");
    return dataURL;
}
wisbucky
  • 33,218
  • 10
  • 150
  • 101