如何在jQuery中发送Ajax请求的FormData对象?

XMLHttpRequest Level 2标准(仍然是一个工作草案)定义了FormData接口。 这个接口可以将File对象附加到XHR请求(Ajax请求)。

顺便说一句,这是一个新的function – 过去,使用“隐藏的iframe技巧”(在我的其他问题阅读 )。

这是如何工作的(例子):

 var xhr = new XMLHttpRequest(), fd = new FormData(); fd.append( 'file', input.files[0] ); xhr.open( 'POST', 'http://example.com/script.php', true ); xhr.onreadystatechange = handler; xhr.send( fd ); 

其中input是一个<input type="file">字段, handler是Ajax请求的成功处理程序。

这在所有浏览器(再次,除了IE浏览器)美丽的作品。

现在,我想使这个function与jQuery的工作。 我试过这个:

 var fd = new FormData(); fd.append( 'file', input.files[0] ); $.post( 'http://example.com/script.php', fd, handler ); 

不幸的是,这是行不通的(一个“非法调用”的错误引发 – 屏幕截图在这里 )。 我假设jQuery期望一个简单的键值对象表示form-field-names / values,而我传入的FormData实例显然是不兼容的。

现在,因为可以将一个FormData实例传递到xhr.send() ,所以我希望它也可以使用jQuery。


更新:

我在jQuery的Bug Tracker上创build了一个“特性票”。 它在这里: http : //bugs.jquery.com/ticket/9995

我被build议使用“Ajax预filter”…


更新:

首先,让我演示一下演示,我想实现什么样的行为。

HTML:

 <form> <input type="file" id="file" name="file"> <input type="submit"> </form> 

JavaScript的:

 $( 'form' ).submit(function ( e ) { var data, xhr; data = new FormData(); data.append( 'file', $( '#file' )[0].files[0] ); xhr = new XMLHttpRequest(); xhr.open( 'POST', 'http://hacheck.tel.fer.hr/xml.pl', true ); xhr.onreadystatechange = function ( response ) {}; xhr.send( data ); e.preventDefault(); }); 

上面的代码导致这个HTTP请求:

multipartformdata

这就是我所需要的 – 我想要“multipart / form-data”内容types!


build议的解决scheme将如下所示:

 $( 'form' ).submit(function ( e ) { var data; data = new FormData(); data.append( 'file', $( '#file' )[0].files[0] ); $.ajax({ url: 'http://hacheck.tel.fer.hr/xml.pl', data: data, processData: false, type: 'POST', success: function ( data ) { alert( data ); } }); e.preventDefault(); }); 

但是,这导致:

wrongcontenttype

正如你所看到的,内容types是错误的…

我相信你可以这样做:

 var fd = new FormData(); fd.append( 'file', input.files[0] ); $.ajax({ url: 'http://example.com/script.php', data: fd, processData: false, contentType: false, type: 'POST', success: function(data){ alert(data); } }); 

processData设置为false可以防止jQuery自动将数据转换为查询string。 有关更多信息,请参阅文档 。

contentType设置为false是非常必要的,否则jQuery 会将其设置错误 。

还有一些尚待提及的技术可供您使用。 首先在ajax参数中设置contentType属性。

以pradeek为例:

 $('form').submit(function (e) { var data; data = new FormData(); data.append('file', $('#file')[0].files[0]); $.ajax({ url: 'http://hacheck.tel.fer.hr/xml.pl', data: data, processData: false, type: 'POST', // This will override the content type header, // regardless of whether content is actually sent. // Defaults to 'application/x-www-form-urlencoded' contentType: 'multipart/form-data', //Before 1.5.1 you had to do this: beforeSend: function (x) { if (x && x.overrideMimeType) { x.overrideMimeType("multipart/form-data"); } }, // Now you should be able to do this: mimeType: 'multipart/form-data', //Property added in 1.5.1 success: function (data) { alert(data); } }); e.preventDefault(); }); 

在某些情况下,当强迫jQuery ajax做非预期的事情时, beforeSend事件是一个很好的select。 一段时间beforeSend ,人们使用beforeSend来重写mimeType,然后在1.5.1中添加到jQuery中。 您应该可以修改before发送事件中jqXHR对象的任何内容。

您可以使用以下代码发送Ajax请求中的FormData对象,

 $("form#formElement").submit(function(){ var formdata = new FormData($(this)[0]); }); 

这与接受的答案非常相似,但是是对于问题主题的实际答案。 这将在FormData中自动提交表单元素,而不需要手动将数据附加到FormDatavariables。

ajax方法看起来像这样,

 $("form#formElement").submit(function(){ var formdata = new FormData($(this)[0]); //append some non-form data also formData.append('other_data',$("#someInputData").val()); $.ajax({ type: "POST", url: postDataUrl, data: formData, processData: false, contentType: false, dataType: "json", success: function(data, textStatus, jqXHR) { //process data }, error: function(data, textStatus, jqXHR) { //process error msg }, }); 

您也可以像这样手动传递FormData对象中的form元素作为参数

 var formElem = $("#formId"); var formdata = new FormData(form[0]); 

希望它有帮助。 ;)

您可以使用$ .ajax beforeSend事件来操作标题。

 beforeSend: function(xhr) { xhr.setRequestHeader('Content-Type', 'multipart/form-data'); } 

有关其他信息,请参阅此链接: http : //msdn.microsoft.com/zh-cn/library/ms536752(v=vs.85).aspx

我认为你不能在ajax中支持所有的浏览器,我可能会说很好,检查这个ajax上传插件,看看他们是如何做到的http://valums.com/ajax-upload/

我这样做,这对我来说,我希望这会帮助:)

  <div id="data"> <form> <input type="file" name="userfile" id="userfile" size="20" /> <br /><br /> <input type="button" id="upload" value="upload" /> </form> </div> <script> $(document).ready(function(){ $('#upload').click(function(){ console.log('upload button clicked!') var fd = new FormData(); fd.append( 'userfile', $('#userfile')[0].files[0]); $.ajax({ url: 'upload/do_upload', data: fd, processData: false, contentType: false, type: 'POST', success: function(data){ console.log('upload success!') $('#data').empty(); $('#data').append(data); } }); }); }); </script> 

如果你想使用ajax提交文件,使用“jquery.form.js”,这很容易提交所有的表单元素。

示例http://jquery.malsup.com/form/#ajaxSubmit

粗糙的看法:

 <form id='AddPhotoForm' method='post' action='../photo/admin_save_photo.php' enctype='multipart/form-data'> 

 <script type="text/javascript"> function showResponseAfterAddPhoto(responseText, statusText) { information= responseText; callAjaxtolist(); $("#AddPhotoForm").resetForm(); $("#photo_msg").html('<div class="album_msg">Photo uploaded Successfully...</div>'); }; $(document).ready(function(){ $('.add_new_photo_div').live('click',function(){ var options = {success:showResponseAfterAddPhoto}; $("#AddPhotoForm").ajaxSubmit(options); }); }); </script> 

JavaScript的:

  function submitForm() { var data1 = new FormData($('input[name^="file"]')); $.each($('input[name^="file"]')[0].files, function(i, file) { data1.append(i, file); }); $.ajax({ url: "<?php echo base_url() ?>employee/dashboard2/test2", type: "POST", data: data1, enctype: 'multipart/form-data', processData: false, // tell jQuery not to process the data contentType: false // tell jQuery not to set contentType }).done(function(data) { console.log("PHP Output:"); console.log( data ); }); return false; } 

PHP:

 public function upload_file(){ foreach ($_FILES as $key ) { $name =time().$key['name']; $path='upload/'.$name; @move_uploaded_file($key['tmp_name'],$path); } 

而不是 – fd.append( 'userfile', $('#userfile')[0].files[0]);

使用 – fd.append( 'file', $('#userfile')[0].files[0]);