Alan Alvarez Alan Alvarez - 2 months ago 14
Ajax Question

How to 'POST' a image through xhttp?

I´m trying to do this:

var http = new XMLHttpRequest();
var url = "guardarImg.php";
var params = $('#form').serialize();
http.open("POST", url, true);
http.setRequestHeader("Content-type", "multipart/form-data");
http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
}
http.send(params);


But is not working, it shows me in my php that 'Image' is not defined, but when I do it through a average Submit it works fine.

All the similar samples I saw work with string data but I need to achieve it with images to make it work later in Intel XDK

What I´m doing wrong?
Can you show me a sample?

Sorry if my question is too basic, I´m a noob with xmlhttp and ajax stuff.

Answer

You have the right idea with regard to $("#form").serialize() but for the mess that is (still) AJAX uploads. Yuck (and shame on me for not noting that detail the first time :-( ).

The problem with file uploads via AJAX is (as is often the case), Internet Explorer. Basically, it didn't support the FormData object until IE10 (which means that, if you care about supporting XP users, they'd better be running not-IE). FormData greatly simplifies the process of uploading stuff via AJAX; if you don't have that, here are your options:

  1. Put a little tiny IFRAME on the page and manage that for the actual file upload.
  2. Encode the form data programmatically using something like JSON and send that via jQuery.
  3. Use a nice plugin that wraps this all for you (and uses one or more of these techniques under the covers).

I'm going to assume you don't care about IE8/9 (pretty much everyone else isn't a problem) and give you a FormData solution. Unlike the previous edit, I'm popping in the whole function in here since it's decently informative. This particular solution uploads an entire form, pulling in the existing fields into the FormData object and treating the files specially.

<!-- Many ways to skin this particular feline; I like this one :-) -->
<form onsubmit="return uploadFiles(this)">
  <!-- Access from PHP using $_FILES["somefile"]["name"][$idx]... -->
  <input type="file" name="somefiles" multiple="1" />
</form>

<script>
  // Function to upload a form via FormData, breaking out files and cutting
  // any non-named elements.  Assumes that there's a #status DIV and the
  // URL is hardcoded.
  function uploadFiles(frm) {
    var formdata = new FormData();
    // I'm doing this to separate out the upload content.  Note that multiple
    // files can be uploaded and will appear as a decently-friendly PHP array
    // in $_FILES.  Note also that this does handle multiple files properly
    // (a default FormData(frm) wouldn't exactly :-( ).
    $(frm).find(":input").each(function(idx, ele) {
      // This is a file field.  Break it out.
      if(ele.files) {
        for(i=0; i<ele.files.length; i++) {
          formdata.append(ele.name + "[" + i + "]", ele.files[i]);
        }
      // Not a file element, so put in the upload iff there's a name.
      } else if(ele.name) {
        formdata.append(ele.name, ele.value);
      }
    });
    // Run the AJAX.
    $.ajax({
      url: "test.php",        // Change Me :-)
      type: "POST",
      data: formdata,
      processData: false,     // Need these to keep jQuery from messing up your form
      contentType: false,
      success: function(data) {
                 $("#status").html(data);
               },
      error: function(xhr, status, error) {
                 $("#status").html("Error uploading file(s): " + error);
             },
    });
    return false;    // Keep the form from submitting
  }
</script>

I have a complete HTML file and corresponding PHP that work at pastebin.

If I were you, I'd actually just use Sebastian's jQuery File Upload if you can. It's got all that modern UI goodness (include progress metering), browser abstraction, and it's MIT licensed to boot. That said, this answer will get you on your way if you just need something to copypasta. Good luck!