Posting File Input as FileReader Binary Data through AJAX Post

59,544

Solution 1

Simply sending the file reference as data (with processData: false) did the job for me at least:

$('#_testButton').bind('click', function () {
    var file = document.getElementById('_testFile').files[0];

    $.ajax({
        url: "/attachmentURL",
        type: "POST",
        data: file,
        processData: false
    });
});

It is described here: https://developer.mozilla.org/en/DOM/XMLHttpRequest/Sending_and_Receiving_Binary_Data#section_3

Sending a string (even if that string represents binary data) will not work because the browser will forcibly turn it into unicode and encode as utf-8 as specified which will corrupt the binary data:

If data is a string Let encoding be UTF-8.

Let mime type be "text/plain;charset=UTF-8".

Let the request entity body be data converted to Unicode and encoded as UTF-8.

Sending a file reference (blob) will do this:

If data is a Blob If the object's type attribute is not the empty string let mime type be its value.

Let the request entity body be the raw data represented by data.

Solution 2

var file;

        $('#_testFile').on("change", function (e) {
            file = e.target.files[0];
        });
        $('#_testButton').click(function () {
            var serverUrl = '/attachmentURL';

            $.ajax({
                type: "POST",
                beforeSend: function (request) {
                    request.setRequestHeader("Content-Type", file.type);
                },
                url: serverUrl,
                data: file,
                processData: false,
                contentType: false,
                success: function (data) {
                    console.log("File available at: ", data);
                },
                error: function (data) {
                    var obj = jQuery.parseJSON(data);
                    alert(obj.error);
                }
            });
        });
Share:
59,544

Related videos on Youtube

Eric H.
Author by

Eric H.

I'm founder and lead developer of Arbolista Software based in Mexico City. I focus on API development, along with Javascript web and mobile applications. Looking for more developers to join our team in Mexico City. Visit http://www.arbolista.mx/en/work-with-us.

Updated on August 06, 2020

Comments

  • Eric H.
    Eric H. over 3 years

    I am trying to post an attachment uploaded to an HTML file input to a web page through a rest API. The API documentation states that the post is a straight binary content as the body of the HTTP request, not a form file upload.

    My code is as follows:

    $('#_testButton').bind('click', function () {
        var file = document.getElementById('_testFile').files[0]
        var reader = new FileReader();
        reader.onload = function () {
            $.ajax({
                url: '/attachmentURL',
                type: 'POST',
                data: reader.result
            })
        }
        reader.readAsBinaryString(file)
    })
    

    I need this to work for a number of different mimeTypes, so I didn't declare it in the code above. However, I have tried declaring contentType:'application/msword' for a .doc file and also tried processData:false and contentType:false.

    The data is being posted where it should. However, when I open the file, I get a message that says mimeType:application/x-empty with an empty file OR a file with a bunch of binary characters. I've tried .doc files and a pdf files and the result is the same for both.

    Does anyone have a clue what I can change to make this work?

  • UltraInstinct
    UltraInstinct almost 12 years
    -1: OP says, the server wants a direct binary content, not a content enveloped in a form data.
  • Esailija
    Esailija almost 12 years
    @EricH. I will hack around a bit and come up with a solution. I simply misunderstood your intentions.
  • UltraInstinct
    UltraInstinct almost 12 years
    Esailija: Haha, looks like you use SO as your social network! @EricH. The way you are doing it, looks fine to me; unless server is looking for something else..
  • Esailija
    Esailija almost 12 years
    @Thrustmaster it should now send the binary data directly as POST data. Tested it too. :P
  • UltraInstinct
    UltraInstinct almost 12 years
    @Esailija -1 Withdrawn, and +1. :)
  • Eric H.
    Eric H. almost 12 years
    Bah Bammm! That worked once I explicitly declared the MIME type. That's easy with contentType:file.type. Thanks so much.
  • Esailija
    Esailija almost 12 years
    @EricH. That's strange, according to specification it should be read automatically from the file: If the object's type attribute is not the empty string let mime type be its value. Oh well, whatever works :)
  • masoud soroush
    masoud soroush over 8 years
    this script for client side ! jQuery
  • Dmitry Sokurenko
    Dmitry Sokurenko almost 6 years
    For me, it has worked well only when I've set the contentType: false or contentType: file.type.