(转载) 上传文件进度事件,进度事件(Progress Events)
转载URL:https://www.w3cmm.com/ajax/progress-events.html
MDN参考:https://developer.mozilla.org/zh-CN/docs/Web/API/ProgressEvent
进度事件(Progress Events)
Progress Events定义了与客户端服务器通信有关的事件。这些事件最早其实只针对XHR操作,但目前也被其它API借鉴。有以下6个进度事件。
- loadstart:在接收到相应数据的第一个字节时触发。
- progress:在接收相应期间持续不断触发。
- error:在请求发生错误时触发。
- abort:在因为调用abort()方法而终止链接时触发。
- load:在接收到完整的相应数据时触发。
- loadend:在通信完成或者触发error、abort或load事件后触发。
每个请求不对触发Loadstart事件开始,接下来是一或多个progress事件,然后触发error、abort或load事件中的一个,最后以触发loadend事件结束。
支持前5个事件的浏览器有Firefox 3.5+、Safari 4+、Chrome、iOS版Safari和Android版WebKit。Opera、IE8+只支持load事件。目前还没有浏览器支持loadend事件。
这些事件大都很直观,但其两个事件有一些细节需要注意。
1.load事件
Firefox在实现XHR对象的某个版本时,曾致力于简化异步交互模型。最终,Firefox实现中引入了load事件,用以替代readystatechange事件。响应接收完毕后将触发Load事件,因此也就没有必要去检查readyState属性了。而onload事件处理程序会接收到一个event对象,其target属性就指向XHR对象实例,因而可以访问到XHR对象的所有方法和属性。然而,并非所有浏览器都为这个事件实现了适当的事件对象。结果,开发人员还是要像下面这样被迫使用XHR对象变量。
function createXHR(){ if(typeofXMLHttpRequest!="undefined"){ returnnewXMLHttpRequest(); }elseif(typeofActiveXObject!="undefined"){ if(typeof arguments.callee.activeXString !="string"){ var versions =["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"]; for(var i =0, len = versions.length; i < len; i++){ try{ var xhr =newActiveXObject(versions[i]); arguments.callee.activeXString = versions[i]; return xhr; }catch(ex){ //跳过 } } } returnnewActiveXObject(arguments.callee.activeXString); }else{ thrownewError("NO XHR object available.") }}
var xhr = createXHR(); xhr.onload =function(){ if((xhr.status >=200&& xhr.status <300)|| xhr.status ==304){ alert(xhr.responseText); }else{ alert("Request was unsuccessful: "+ xhr.status); }}; xhr.open("get","altevents.php",true); xhr.send(null);
只要浏览器接收到服务器的响应,不管其状态如何,都会触发load事件。而这意味着你必须要检查status属性,才能确定数据是否真的已经可用了。Firefox、Operan、Chrome和Safari都支持load事件。
2.progress事件
progress事件会在浏览器接收新数据期间周期性地触发。而onprogress事件处理程序会接收到一个event对象,其target属性是XHR对象,但包含着三个额外的属性:lengthComputable、loaded和total。其中,lengthComputable是一个表示进度信息是否可用的布尔值,loaded表示已经接收的字节数,loaded表示根据Content-Length响应头部确定的预期字节数。有了这些信息,我们就可以为用户创建一个进度指示器了。下面展示了为用户创建进度指示器的一个示例。
var xhr = createXHR(); xhr.onload =function(){ if((xhr.status >=200&& xhr.status <300)|| xhr.status ==304){ alert(xhr.responseText); }else{ alert("Request was unsuccessful: "+ xhr.status); }};//get请求一般用来获取下载进度 xhr.onprogress =function(event){ var divStatus = document.getElementById("status"); if(event.lengthComputable){ divStatus.innerHTML ="Recived"+event.loaded +" of "+event.total +" bytes"; }} xhr.open("get","altevents.php",true); xhr.send(null);
为确保正常执行,必须在调用open()方法之前添加onprogress事件处理程序。在前面的例子中,每次触发progress事件,都会以新的状态信息更新HTML元素的内容。如果响应头部中包含Content-Length字段,那么也可以利用此信息来计算从响应中已经接收到的数据的百分比。
当请求类型为post时需要监听xhr.upload。
//post一般用来获取上传进度 xhr.upload.onprogress =function(e){if(e.lengthComputable){ console.log(e.loaded / e.total *100)}}
下面是一个get请求综合示例:
<divid="status"></div><scripttype="text/javascript"> function createXHR(){ if(typeofXMLHttpRequest!="undefined"){ returnnewXMLHttpRequest(); }elseif(typeofActiveXObject!="undefined"){ if(typeof arguments.callee.activeXString !="string"){ var versions =["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"], i, len; for(i =0, len = versions.length; i < len; i++){ try{ var xhr =newActiveXObject(versions[i]); arguments.callee.activeXString = versions[i]; return xhr; }catch(ex){ //跳过 } } } returnnewActiveXObject(arguments.callee.activeXString); }else{ thrownewError("No XHR object available."); } } window.onload =function(){ var xhr = createXHR(); xhr.onload =function(){ if((xhr.status >=200&& xhr.status <300)|| xhr.status ==304){ alert(xhr.responseText); }else{ alert("Request was unsuccessful: "+ xhr.status); } }; xhr.onprogress =function(event){ var divStatus = document.getElementById("status"); if(event.lengthComputable){ divStatus.innerHTML ="接收到 "+ event.loaded +" of "+ event.total +" bytes"; } }; xhr.open("get","altevents.php",true); xhr.send(null); };</script>
altevents.php
文件示例代码:
<!-- altevents.php --><?php header("Content-Type: text/plain"); header("Content-Length: 27"); echo "Some data"; flush(); echo "Some data"; flush(); echo "Some data"; flush();?>