2

I am trying to upload a file to a generic HttpHandler in c#. I get the file using drag and drop events:

 $s("#dropArea")
    .on("drop", function(e) {
        e.preventDefault && e.preventDefault();

        var file = e.originalEvent.dataTransfer.files[0];

        var reader = new FileReader();

    reader.onload = function(evt) {
        $s.ajax({
            url: MY_SERVER_URL,
            type: "POST",
            data: reader.result,
            headers: {
                "x-file-name": file.name
            }                
        });
    };
    reader.readAsDataURL(file);

this seems to work fine, but when posted to the ashx page, I try decode the image like so:

var form = context.Request.Form[0];
var attachment = form.Split(new[] {","}, StringSplitOptions.RemoveEmptyEntries)[1];

byte[] data = Convert.FromBase64String(attachment);

When I try to write byte[] data to the disk, the resulting file is not correct. Where am I going wrong?

edit: I have also tried using FormData, but the Request.Form and Request.Files collections are always empty and I have to parse the boundaries manually. This is the code I was using to do that:

var formData = new FormData();
    formData.append(file.name, file);

    $s.ajax({
        url: MY_SERVER_URL,
        type: "POST",
        data: formData,
        processData: false,
        contentType: 'multipart/form-data',
        mimeType: 'multipart/form-data',
        headers: {
            "x-file-name": file.name            
    });
7
  • 2
    And why wouldn't you do like normal people, and use a formData object to upload the image ? Commented Sep 18, 2014 at 20:42
  • @adeneo because the Request.Form collection is always empty when I do that. I set the content type to "multipart/form-data" in jQuery and it just comes through Request.InputStream, which then requires me to parse out the boundaries. Commented Sep 18, 2014 at 20:46
  • In the second one, remove the headers and set the contentType to false, and see if it works. Commented Sep 18, 2014 at 20:50
  • @adeneo thank you, that was it. Why does setting the contentType to false change it? I didn't see in the jquery docs where that behavior is described. Commented Sep 18, 2014 at 21:07
  • 2
    Setting the contentType to false forces jQuery not to add a Content-Type header, and subsequnetly removing the boundary string, it has to be set to false to work with files. Commented Sep 18, 2014 at 21:14

2 Answers 2

2

When sending files with jQuery's $.ajax one has to set the processData and contentType options to false.

Setting the processData to false makes sure jQuery doesn't process the formData object in any way.

Setting the contentType to false makes sure jQuery doesn't add a boundary, something it would normally do. That is, jQuery adds the contentType, and a boundary, so it looks something like :

Content-Type=multipart/form-data; boundary=----------------993434535254

we don't want jQuery to set a certain boudary, as then the serverside wouldn't understand what's going on, so to avoid it the contentType has to be set to false when sending files.

var formData = new FormData();

    formData.append(file.name, file);

$s.ajax({
    url: MY_SERVER_URL,
    type: "POST",
    data: formData,
    processData: false,
    contentType: false,
});

and that's really all the options that are needed to send files with jQuery

Sign up to request clarification or add additional context in comments.

Comments

0

What browser did you try this on? what version of jquery are you using for this? Include more specifics to increase your chance of finding the answer.

Since you are uploading images you may want to use a component that can resize/convert or whatever as well or your users might upload the wrong type, may want to consider a component that helps you with this.

File uploads on the web can be tricky, instead of trying to re-invent the wheel, save yourself some hair-pulling and pick a library like plupload that people have worked on for many years.

Even if you get this code above to work in your specific case and you think it works, it will very likely be buggy in every single scenario you have not tested. With web file uploads every little detail down to the headers sent with the file transfer have to be exactly right or it will not work. If any of your files are large depending on what webserver you are using you may need to tweak those settings, etc.

I don't know what is wrong with your code but I do know that to do this properly is a lot more complex than what you have above.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.