前段时间项目中有个文件上传要监听上传进度的需求,在网上看了检测进度的方法都大同小异,几乎都是一样的方法,但是这种方法上传小文件似乎看不出什么问题,但是上传大文件的时候(例如3G的大文件,进度条到100%之后,点击保存上传文件的大小为0,也就是说文件还没上传成功,进度条就到100%了,这到底是什么原因呢?????搞的我头皮发麻。。。。。最后突然在网上看到了别人提问的评论,一下子就搞定了,内心无比喜悦)!!!
这个是原文章链接:jquery ajax xhr监听上传进度显示不准确,求解_百度知道
文章中提到因为 XMLHttpRequest.onProgress 事件能拿到的是网络传输的字节而已;而“上传进度已完成”,实际是指浏览器已经把文件传输给了服务端;但是服务端还有额外的处理时间,这段时间对浏览器来说是不可感知的,它不知道服务端处理需要多久
一般处理思路有这么几种:
1、上传进度设置一个最大值,比如 99%,只有当服务端真正返回结果时才会变到 100%,这种方法最为简单粗暴;
2、尽量减少服务端处理的时间,例如收到文件后交给异步队列去处理,立刻返回给客户端响应,这种方法需要额外做的事件比较多,开发难度更高一些;
3、客户端分片上传,把大文件变成若干段小“文件”,缺点是浏览器只有支持 HTML5 才支持 FormData 分片。
我是采用的第一种方法,简单粗暴又好用
大概代码:
<%--进度条--%>
<div class="imStrategyUploadBar" style="display:none">
<%--进度条这边的max也要从100改到99--%>
<progress class="imStrategyProgressBar" value="0" max="99" style="height: 5px;width:70.5%;margin-left:87.61px;"></progress>
<span class="imStrategyPercentage"></span>//显示进度条百分比
</div>
var request = $.ajax({
url: '',
type: 'POST',
data: formData,
processData: false,// 不处理发送的数据
contentType: false,// 不设置Content-Type请求头
cache: false,
xhr: function () {
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) { //检查upload属性是否存在
//绑定progress事件的回调函数
myXhr.upload.addEventListener('progress', progressHandlingFunction, false);
}
return myXhr; //xhr对象返回给jQuery使用
},
beforeSend: function () {
$(".imStrategyProgressBar").val('');
$(".imStrategyPercentage").text('');
},
success: function (responseStr) {
if (null != responseStr || responseStr != undefined) {
var data = $.parseJSON(responseStr);
}
},
});
$(".ui-dialog .ui-dialog-buttonpane button:last-child").on('click', function () {
request.abort();//大文件上传过程中关闭弹框,再次打开弹框,刚刚的文件还没上传成功,就会出现进度条一直闪烁的情况,所以关闭弹框的时候要中断ajax请求
});
$(".ui-dialog .ui-dialog-titlebar-close").on('click', function () {
request.abort();
});
}
/**
* 进度条
* @param e
*/
function progressHandlingFunction(e) {
var curr = e.loaded;//已经上传文件大小情况
var total = e.total;//附件总大小
var process = curr / total * 99;//已上传的百分比-----------以前是total*100,改成99
$(".imStrategyProgressBar").val(process);
$(".imStrategyPercentage").text(Math.floor(process) + "%");
}