Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

POSTing a Blob with FormData via jQuery.ajax

Tags:

html

jquery

ajax

I've seen this question asked many times, but as much as I try, I'm still seeing no results:

How can I append a Blob to form data and POST it via jquery?

var reader = FileReader(); 
reader.readAsBinaryString(f);
reader.onload = function() {
    var slice = reader.result.slice(0,100, {type: "application/octet-stream"});

    var formdata = new FormData();
    formdata.append("blobData", slice); // I have verified via console.log(slice) that this has data
    formdata.append("blobName", "Photo");

    send(formdata);
}

function send(data) {
    $.ajax({
        url: "/upload",
        type: "POST",
        data: data,    
        cache: false,
        contentType: false,
        processData: false
    });
}

All the non-blob key/values are in the request, and even the blob's key... but not the blob data.

Missing data

Interestingly, when I post using Firefox instead of Chrome, I get a little bit of data up there.. but not much (this should be up to 2 MB worth of data... it's 7 bytes)

enter image description here

like image 511
Brian D Avatar asked Mar 25 '13 04:03

Brian D


1 Answers

I recently encountered this exact problem and have the solution.

The core issue is that the value of reader.result passed to reader.onload by readAsBinaryString is a string, not a blob. Sounds obvious really but I also assumed I was working with a blob. Since String and Blob objects both have a slice method the variable slice, whilst set with data that looks like binary data, is still just a string. The String.slice() method works exactly the same as the Blob.slice() method and just ignores the third parameter, which is why you don't notice what's really happening.

According to the FormData spec any value that is not a Blob or File object is converted to a string. It appears that the slice string is being truncated at the first non-ASCII character (I'm just guessing as to the exact reason, but the important point is that the string is definitely being truncated when it's appended to formdata).

The solution is to convert reader.result into a blob first:

reader.onload = function() {
    var blob = new Blob([reader.result]), 
        slice = blob.slice(0,100, {type: "application/octet-stream"});

    var formdata = new FormData();
    formdata.append("blobData", slice);
    formdata.append("blobName", "Photo");

    send(formdata);
}

(The array is a requirement of the Blob constructor).

Now slice is a blob, since the Blob.slice() method returns a Blob object, and can be appended to formdata without being mangled by string conversion.

like image 103
Stephen Blair Avatar answered Nov 10 '22 21:11

Stephen Blair