关于javascript:XMLHttpRequest POST multipart / form-data

XMLHttpRequest POST multipart/form-data

我想在JavaScript中使用XMLHttpRequest来发布包含文件类型输入元素的表单,以便避免页面刷新并获得有用的XML。

我可以使用JavaScript将表单上的target属性设置为MSIE的iframe或Mozilla的对象,而无需刷新页面即可提交表单,但这有两个问题。 较小的问题是目标与W3C不兼容(这就是为什么我在JavaScript中而不是在XHTML中设置目标)。 主要问题是onload事件不会触发,至少在OS X Leopard的Mozilla上不会触发。 此外,XMLHttpRequest可以提供更漂亮的响应代码,因为返回的数据可以是XML,而不像iframe那样局限于XHTML。

提交表单的结果类似于HTTP:

1
2
3
4
5
6
7
8
9
10
11
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>

如何获取XMLHttpRequest对象的send方法来复制上述HTTP流?


您可以自己构造" multipart / form-data"请求(有关更多信息,请访问http://www.faqs.org/rfcs/rfc2388.html),然后使用send方法(即xhr.send( your-multipart-form-data))。同样,但更简单,在Firefox 4+(在Chrome 5+和Safari 5+中)中,您可以使用FormData接口来帮助构造此类请求。 send方法适用于文本内容,但是如果要发送二进制数据(例如图像),则可以借助sendAsBinary方法来实现,该方法始于Firefox 3.0。有关如何通过XMLHttpRequest发送文件的详细信息,请参阅http://blog.igstan.ro/2009/01/pure-javascript-file-upload.html。


无法访问javascript中的文件输入字段,因此没有针对ajax文件上传的仅javascript解决方案。

有一些解决方法,例如使用iframe。

另一种选择是使用SWFUpload或Google Gears之类的东西


这是使用FormData的最新方式(完整文档@MDN)

脚本:

1
2
3
4
5
6
7
8
9
10
11
12
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();
});

(从此基本形式开始)

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

再次感谢Alex Polo的回答


Content-Disposition: form-data, name

您应该使用分号,如下所示:Content-Disposition:form-data;名称


我对您指定的onload事件感到困惑,是在页面上还是在iframe上?
第一个答案是正确的,没有办法使用纯粹的xmlhttprequest来执行此操作,如果您要实现的目标是在iframe上存在响应后触发某种方法,则只需使用DOM脚本检查它是否已包含内容,然后触发该方法即可。

将onload事件附加到iframe

1
2
3
4
5
if(window.attachEvent){
 document.getElementById(iframe).attachEvent('onload', some_method);
}else{
 document.getElementById(iframe).addEventListener('load', some_method, false);
}

您将需要发布到IFrame以使其正常工作,只需在您指定IFrame ID的表单中添加目标属性即可。像这样:

1
2
3
4
5
6
<wyn>
<form method="post" target="myiframe" action="handler.php">
...
</form>
<iframe id="myiframe" style="display:none" />
</wyn>


我不明白为什么iframe(一种看不见的内容)暗示XHTML而不包含任何内容。如果您使用iframe,则可以设置onreadystatechange事件并等待"完成"。接下来,您可以使用frame.window.document.innerHTML(请纠正我)以获取字符串结果。

1
2
3
4
5
6
7
8
var lFrame = document.getElementById('myframe');
lFrame.onreadystatechange = function()
{
   if (lFrame.readyState == 'complete')
   {
      // your frame is done, get the content...
   }
};