Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a Blob from a local file in phonegap on android

I am trying to upload a file to amazon S3 from a phonegap app on android. I already have the code working for iOS. But I've got a trouble making it work on android. The problem is that I do not know how to create the Blob object properly. On iOS I just do this:

blob = new Blob([evt.target.result], {type: "image/png"});

It is uploaded just fine. On android one can not use the Blob constructor (see here), but I could not manage to get the file data correctly into the Blob object using WebKitBlobBuilder.

Here is how I retrieve the file data, there are two approaches and both pass without errors, but the resulting file on the S3 is empty:

window.resolveLocalFileSystemURI(url, function(e){
    e.file(function(f){
        var reader = new FileReader();
        reader.onloadend = function(evt) {
        // This way also did not work:
        //    var builder = new WebKitBlobBuilder();
        //    builder.append(evt.target.result);
        //    blob = builder.getBlob("image/png");

            var blob = null;
            var builder = new WebKitBlobBuilder();
            for(var i = 0; i < evt.target.result.length; i++){
                builder.append(evt.target.result[i]);
            }
            blob = builder.getBlob("image/png");
            uploadToS3(filename, s3url, blob);
        };
        reader.readAsArrayBuffer(f);
    });
}, function(e){
    console.log("error getting file");
    error();
});

also, here is the uploadToS3 function:

var uploadToS3 = function(filename, s3url, fileData) {
    var xhr = createCORSRequest('PUT', s3url);
    if(!xhr) {
        console.log('CORS not supported');
        error();
        return;
    }
    xhr.onload = function () {
        if(xhr.status == 200) {
            console.log('100% - Upload completed.');
            callback(filename); //callback defined in outer context
        }
        else {
            console.log('0% - Upload error: ' + xhr.status);
            console.log(xhr.responseText);
            error();
        }
    };
    xhr.onerror = function () {
        console.log(0, 'XHR error.');
        error();
    };
    xhr.upload.onprogress = function (e) {
        if(e.lengthComputable) {
            var percentLoaded = Math.round((e.loaded / e.total) * 100);
            var label = (percentLoaded == 100) ? 'Finalizing.' : 'Uploading.';
            console.log(percentLoaded + "% - " + label);
        }
    };
    xhr.setRequestHeader('Content-Type', "image/png");
    //xhr.setRequestHeader('x-amz-acl', 'public-read');
    xhr.send(fileData);
};

EDIT: I checked the filesize by logging evt.target.result.byteLength and it was ok, so evt.target.result contains image data. Still there is a problem with the upload - I checked the s3 storage and file size is 0, so I am not constructing the Blob correctly.

like image 750
pckill Avatar asked Oct 22 '22 01:10

pckill


1 Answers

So this is an android bug after all, which was not fixed since at least Nov 2012.

Here is an article I found which is directly related to my problem: https://ghinda.net/article/jpeg-blob-ajax-android/

It also provides a workaround for the bug, which is to send ArrayBuffer directly, without creating a Blob. In my case I had to send evt.target.result directly.

like image 120
pckill Avatar answered Oct 27 '22 11:10

pckill