异步提交文件
异步提交表单对于现代AJAX程序来说是一件轻而易举的事,如果使用jQuery等库的话更无需考虑浏览器的差异,简单的一句$.post 搞定,但如果要上传文件呢?jQuery的异步请求方法并没有提供异步提交文件的功能,这个时候我们可以使用jQuery的Form插件(http://malsup.com/jquery/form/)来完成这个功能,或者我们可以搞清楚原理,自己实现一个。
使用jQuery的form插件实现异步提交文件
使用form插件实现异步提交表单非常简单,只需要针对form表单执行ajaxForm初始化即可
<form id="myForm" action="/upload" method="post" enctype="multipart/form-data"> 描述:<input name="desc"> 文件:<input name="file" type="file"> <button id="submit" type="submit">提交</button> </form> <script> $('#myForm').ajaxForm(function() { alert("提交成功"); }); </script>
XMLHttpRequest2对异步提交表单的支持
现代的浏览器对异步请求提供了功能更强大的支持,这就是我们要隆重介绍的XMLHttpRequest2。顺便提一句,XMLHttpRequest2并不属于HTML5,它是个新的、功能强大的API。我们可以构造XMLHttpRequest2的FormData对象并放进去我们想要的文本、文件等。
$('#myForm').on('submit', function() { var formElem = this; var formData = new FormData(); $('#myForm').find('input').each(function() { if (this.type=='file' && this.files.length>0) { for (var i= 0; i<this.files.length; i++) { formData.append(this.name, this.files.item(i)); } } else { formData.append(this.name, this.value); } }); $.ajax({ url: formElem.action, data: formData, processData: false, contentType: false, type: formElem.method, success: function(data){ alert(data); } }); return false; });
低级浏览器下的解决方法
XMLHttpRequest2只有IE10+才支持,那么对于低版本的浏览器如何实现呢?我们可以构建一个虚拟表单,并提交到iframe里的方式。
$('#myForm').on('submit',function() { var jQorigForm = $(this); // 创建一个用于存放结果的iframe var iframeName = 'form-target-'+new Date().valueOf(); var jQiframe = $('<iframe id="'+iframeName+'" name="'+iframeName+'" style="position:absolute;left:-9999px;top:-9999px"></iframe>') .appendTo('body'); // 创建一个临时表单,令其提交到iframe中 var jQform = jQorigForm.clone() .html('') .appendTo('body') .attr('target',iframeName) .css({position:'absolute',left:'-9999px',top:'-9999px'}); // 拷贝输入框到临时表单 jQorigForm.find('input').each(function() { var jQinput = $(this); var jQnewInput = jQinput.clone(); if (this.type=='file') { // 由于FileInput不能赋值,所以只能交换两个form的元素的权宜之计 jQinput.before(jQnewInput); jQinput.appendTo(jQform); } else { jQnewInput.appendTo(jQform); } }); // 提交临时表单 jQform.submit().remove(); // 设个定时从iframe中读取结果 var interval = setInterval(function() { var content = jQiframe.contents().find('body').html(); if (content) { alert(content); jQiframe.remove(); clearInterval(interval); } }, 400); return false; });