XMLHttpRequest POST multipart/form-data
Asked Answered
C

7

20

I want to use XMLHttpRequest in JavaScript to POST a form that includes a file type input element so that I can avoid page refresh and get useful XML back.

I can submit the form without page refresh, using JavaScript to set the target attribute on the form to an iframe for MSIE or an object for Mozilla, but this has two problems. The minor problem is that target is not W3C compliant (which is why I set it in JavaScript, not in XHTML). The major problem is that the onload event doesn't fire, at least not on Mozilla on OS X Leopard. Besides, XMLHttpRequest would make for prettier response code because the returned data could be XML, not confined to XHTML as is the case with iframe.

Submitting the form results in HTTP that looks like:

Content-Type: multipart/form-data;boundary=<boundary string>
Content-Length: <length>
--<boundary string>
Content-Disposition: form-data, name="<input element name>"

<input element value>
--<boundary string>
Content-Disposition: form-data, name=<input element name>"; filename="<input element value>"
Content-Type: application/octet-stream

<element body>

How do I get the XMLHttpRequest object's send method to duplicate the above HTTP stream?

Cullis answered 30/9, 2008 at 22:27 Comment(1)
You've accepted an answer after 9 years! You are the second with it on the stackexchange.Mabuse
W
27

You can construct the 'multipart/form-data' request yourself (read more about it at http://www.faqs.org/rfcs/rfc2388.html) and then use the send method (ie. xhr.send(your-multipart-form-data)). Similarly, but easier, in Firefox 4+ (also in Chrome 5+ and Safari 5+) you can use the FormData interface that helps to construct such requests. The send method is good for text content but if you want to send binary data such as images, you can do it with the help of the sendAsBinary method that has been around starting with Firefox 3.0. For details on how to send files via XMLHttpRequest, please refer to http://blog.igstan.ro/2009/01/pure-javascript-file-upload.html.

Weaponry answered 21/11, 2010 at 23:2 Comment(2)
Holy ***. Thank you! Tried to figure out how to do this manually for an hour with my server unable to parse what I sentCourtnay
It would be great to have a little summary of what you find important in those links in case the servers are shut down.Vatic
A
5

There isn't any way to access a file input field inside javascript so there isn't a javascript only solution for ajax file uploads.

There are workaround like using an iframe.

The other option would be to use something like SWFUpload or Google Gears

Astrology answered 30/9, 2008 at 22:42 Comment(0)
C
1

Here is an up to date way using FormData (full doc @MDN)

Script:

var form = document.querySelector('#myForm');
form.addEventListener("submit", function(e) {
    var xhr = new XMLHttpRequest();
    xhr.open("POST", this.action);
    xhr.addEventListener("load", function(e) {
        // Your callback
    });

    xhr.send(new FormData(this));

    e.preventDefault();
});

(from this basic form)

<form id="myForm" action="..." method="POST" enctype="multipart/form-data">
    <input type="file" name="file0">
    <input type="text" name="some-text">
    ...
</form>

Thanks again to Alex Polo for his answer

Courtnay answered 31/12, 2017 at 13:58 Comment(0)
U
0

I don't see why iframe (an invisible one) implies XHTML and not ANY content. If you use an iframe you can set the onreadystatechange event and wait for 'complete'. Next you could use frame.window.document.innerHTML (please someone correct me) to get the string result.

var lFrame = document.getElementById('myframe');
lFrame.onreadystatechange = function()
{
   if (lFrame.readyState == 'complete')
   {
      // your frame is done, get the content...
   }
};
Umbilicus answered 30/9, 2008 at 22:42 Comment(0)
M
0

You will need to POST to an IFrame to get this to work, simply add a target attribute to your form, where you specify the IFrame ID. Something like this:


<form method="post" target="myiframe" action="handler.php">
...
</form>
<iframe id="myiframe" style="display:none" />

Metastasis answered 30/9, 2008 at 22:45 Comment(0)
T
0

i am confuse about the onload event that you specified, it is on the page or on iframe?, the first answer is correct theres no way to do this using purely xmlhttprequest, if what you want to acheive is triggering some method once the response exist on iframe, simply check if it has content already or not using DOM scripting, then fire the method.

to attach onload event to the iframe

if(window.attachEvent){
 document.getElementById(iframe).attachEvent('onload', some_method);
}else{
 document.getElementById(iframe).addEventListener('load', some_method, false);
} 
Townsville answered 4/10, 2008 at 18:15 Comment(0)
E
0

Content-Disposition: form-data, name

You should use semicolon, like this: Content-Disposition: form-data; name

Ernaernald answered 29/6, 2011 at 15:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.