表单:
<form id="uploadForm" enctype="multipart/form-data">
<input id="file" type="file" name="file"/>
<button id="btn-submit" type="button">上传</button>
</form>
<progress style="width:100%;display: none;"></progress>
<span id="progress" style="float:left">0%</span>
javascript实现代码:
var formData = new FormData($('#uploadForm')[0]);
$.ajax({
type: "POST",
url: "${ctx}/upload",
data: formData,
dataType:"json",
xhr : function() { //获取ajaxSettings中的xhr对象,为它的upload属性绑定progress事件的处理函数
myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) { //检查upload属性是否存在
//绑定progress事件的回调函数
myXhr.upload.addEventListener(
'progress',
progressHandlingFunction,
false);
}
return myXhr; //xhr对象返回给jQuery使用
},
beforeSend: function() {
$("#btn-submit").attr("disabled", true);//提交表单前的处理,重复提交表单
$("#btn-submit").html("正在上传...");
},
success: function(data) {
if (data.code==0) {
alert('操作成功');
} else {
alert(data.msg);
}
refreshPage();
},
error:function(e){
console.log(e);
},
complete:function(){
$("#btn-submit").attr("disabled", false);
$("#btn-submit").html("上传");
},
contentType : false, //必须false才会自动加上正确的Content-Type
processData : false //必须false才会避开jQuery对 formdata 的默认处理
});
//上传进度回调函数:
function progressHandlingFunction(e) {
if (e.lengthComputable) {
$('progress').attr({
value : e.loaded,
max : e.total
}); //更新数据到进度条
var percent = e.loaded / e.total * 100;
$('#progress').html(percent.toFixed(2) + "%");
}
}
归纳总结:
首先form标签需要添加 enctype="multipart/form-data"属性。
其次就是要注意contentType和processData参数。
Request Headers:在 multipart/form-data 后面有boundary以及一串字符,这是分界符,后面的一堆字符串是随机生成的,目的是防止上传文件中出现分界符导致服务器无法正确识别文件起始位置。
contentType = false,设置为false。因为当我们在 form 标签中设置了enctype="multipart/form-data",这样请求中的 contentType 就会默认为 multipart/form-data 。而我们在 ajax 中 contentType 设置为 false 是为了避免 JQuery 对其操作,从而失去分界符,而使服务器不能正常解析文件。
processData = false 默认为true,默认情况下,发送的数据将被转换为对象(从技术角度来讲并非字符串)以配合默认内容类型"application/x-www-form-urlencoded"。如果要发送DOM树信息或者其他不希望转换的信息,请设置为false。
processData 设置false,因为data值是FormData对象,不需要对数据做处理。