XMLHttpRequest POST multipart/form-data

20

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

我可以使用JavaScript将表单的目标属性设置为MSIE的iframe或Mozilla的object,以实现无需页面刷新的提交,但这有两个问题。其一是目标属性不符合W3C标准(这就是为什么我在JavaScript中设置它而不是在XHTML中设置)。其二是onload事件不会触发,至少在OS X Leopard上的Mozilla上不会触发。此外,使用XMLHttpRequest可以使响应代码更加优美,因为返回的数据可以是XML,不像使用iframe只能限制于XHTML。

提交表单会产生类似以下的HTTP:

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流?


你在9年后接受了一个答案!你是StackExchange上第二个这样做的人。 - peterh
7个回答

27
您可以自己构建“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

天啊!谢谢!我试图手动解决这个问题一个小时,但我的服务器无法解析我发送的内容。 - Romuald Brunet
如果服务器关闭,那么在这些链接中找到重要信息的小结将非常有用。 - everyone

5

在JavaScript中没有办法访问文件输入字段,因此没有JavaScript的解决方案可以用于Ajax文件上传。

有一些变通方法,例如使用iframe

另一个选择是使用SWFUploadGoogle Gears等工具。


0
你应该使用分号,像这样:Content-Disposition: form-data; name。

0
你需要通过POST请求将数据发送到一个IFrame来使它工作,只需要在你的表单中添加一个target属性,指定IFrame的ID即可。示例代码如下:

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


0

我不明白为什么使用iframe(一个不可见的)就意味着XHTML而不是任何内容。如果您使用iframe,可以设置onreadystatechange事件并等待“完成”。接下来,您可以使用frame.window.document.innerHTML(请有人纠正我)获取字符串结果。

var lFrame = document.getElementById('myframe');
lFrame.onreadystatechange = function()
{
   if (lFrame.readyState == 'complete')
   {
      // your frame is done, get the content...
   }
};

0
我对你指定的 onload 事件感到困惑,它是在页面上还是在 iframe 上?第一个答案是正确的,如果您想要的是一旦 iframe 上存在响应就触发某些方法,则无法仅使用 xmlhttprequest 来实现此操作,只需使用 DOM 脚本检查其是否已经拥有内容,然后触发该方法。
将 onload 事件附加到 iframe。
if(window.attachEvent){
 document.getElementById(iframe).attachEvent('onload', some_method);
}else{
 document.getElementById(iframe).addEventListener('load', some_method, false);
} 

0

这里有一个使用FormData的最新方法(完整文档@MDN

脚本:

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();
});

(从这个基本形式)

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

再次感谢Alex Polo的回答


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接