Javascript 如何从XMLHttpRequest获得进度
是否可以获取XMLHttpRequest的进度(上传字节,下载字节) 当用户上传大文件时,显示进度条会很有用。标准API似乎不支持它,但可能在任何浏览器中都有一些非标准的扩展?毕竟,这似乎是一个非常明显的特性,因为客户端知道上传/下载了多少字节Javascript 如何从XMLHttpRequest获得进度,javascript,ajax,progress-bar,Javascript,Ajax,Progress Bar,是否可以获取XMLHttpRequest的进度(上传字节,下载字节) 当用户上传大文件时,显示进度条会很有用。标准API似乎不支持它,但可能在任何浏览器中都有一些非标准的扩展?毕竟,这似乎是一个非常明显的特性,因为客户端知道上传/下载了多少字节 注意:我知道“轮询服务器以获取进度”选项(这就是我现在正在做的)。这方面的主要问题(除了复杂的服务器端代码)是,通常在上传大文件时,用户的连接被完全阻塞,因为大多数ISP提供的上游服务都很差。因此,提出额外的要求并不像我希望的那样反应迅速。我希望有一种方
注意:我知道“轮询服务器以获取进度”选项(这就是我现在正在做的)。这方面的主要问题(除了复杂的服务器端代码)是,通常在上传大文件时,用户的连接被完全阻塞,因为大多数ISP提供的上游服务都很差。因此,提出额外的要求并不像我希望的那样反应迅速。我希望有一种方法(可能是非标准的)来获取这些信息,浏览器随时都可以使用它。最有希望的方法之一似乎是打开第二个通信通道返回服务器,询问服务器传输完成了多少。如果您可以访问apache安装并信任第三方代码,则可以使用(如果您使用apache,还可以使用) 否则,您必须编写一个脚本,可以在带外点击以请求文件的状态(例如检查tmp文件的文件大小)
我相信firefox 3中正在进行一些工作,将上传进度支持添加到浏览器中,但这不会进入所有浏览器并在一段时间内被广泛采用(更遗憾的是)。对于上传的总数,似乎没有办法处理,但有一些类似于您希望下载的内容。readyState为3后,您可以定期查询responseText以获取下载的所有内容,直到所有内容都可用为止(在IE中不起作用),此时它将转换为readyState 4。在任何给定时间下载的总字节数将等于responseText中存储的字符串中的总字节数
对于上传问题的“全有或全无”方法,由于您必须传递一个用于上传的字符串(并且可以确定该字符串的总字节数),因此为readyState 0和1发送的总字节数将为0,为readyState 2发送的总字节数将为您传递的字符串中的总字节数。readyState 3和4中发送和接收的总字节数将是原始字符串中的字节数加上responseText中的总字节数之和。使用纯javascript实现这一点的唯一方法是实现某种轮询机制。 您需要以固定的间隔(例如每5秒)发送ajax请求,以获取服务器接收的字节数 更有效的方法是使用flash。flex组件定期发送一个包含已上载字节数的“进度”事件。 如果您需要坚持使用javascript,那么actionscript和javascript之间就有了桥梁。 好消息是,这项工作已经为您完成:) 此库允许在flash progress事件上注册javascript处理程序
此解决方案的优点是不需要服务器端的辅助资源。Firefox支持。对于上载的字节,它非常简单。只需监视
xhr.upload.onprogress
事件。浏览器知道必须上载的文件大小和上载数据的大小,因此可以提供进度信息
对于下载的字节(当使用xhr.responseText
获取信息时),这有点困难,因为浏览器不知道服务器请求中将发送多少字节。在这种情况下,浏览器只知道它接收的字节的大小
有一个解决方案可以解决这个问题,在服务器脚本上设置Content Length
头就足够了,以便获得浏览器将要接收的字节的总大小
有关更多信息,请访问
例如:
我的服务器脚本读取zip文件(需要5秒钟):
现在我可以监视服务器脚本的下载过程,因为我知道它的总长度:
function updateProgress(evt)
{
if (evt.lengthComputable)
{ // evt.loaded the bytes the browser received
// evt.total the total bytes set by the header
// jQuery UI progress bar to show the progress on screen
var percentComplete = (evt.loaded / evt.total) * 100;
$('#progressbar').progressbar( "option", "value", percentComplete );
}
}
function sendreq(evt)
{
var req = new XMLHttpRequest();
$('#progressbar').progressbar();
req.onprogress = updateProgress;
req.open('GET', 'test.php', true);
req.onreadystatechange = function (aEvt) {
if (req.readyState == 4)
{
//run any callback here
}
};
req.send();
}
结果
更改内容
功能更新\u进度(e)
{
if(如长度可计算)
{
风险值百分比=数学四舍五入((e.loaded/e.total)*100);
log(“百分比”+百分比+“%”);
}
其他的
{
log(“由于总大小未知,无法计算进度信息”);
}
}
函数传输_complete(e){console.log(“传输完成”);}
函数传输失败(e){console.log(“传输文件时出错。”);}
函数传输_cancelled(e){console.log(“用户已取消传输”);}
函数get\u post\u ajax()
{
var-xhttp;
if(window.XMLHttpRequest){xhttp=newxmlhttprequest();}//现代浏览器代码}
else{xhttp=newActiveXObject(“Microsoft.XMLHTTP”);}//IE6、IE5的代码
xhttp.onprogress=更新进度;
xhttp.addEventListener(“加载”,传输完成,错误);
xhttp.addEventListener(“错误”,传输失败,错误);
xhttp.addEventListener(“中止”,传输被取消,错误);
xhttp.onreadystatechange=函数()
{
如果(xhttp.readyState==4&&xhttp.status==200)
{
document.getElementById(“demo”).innerHTML=xhttp.responseText;
}
};
xhttp.open(“GET”http://it-tu.com/ajax_test.php“,对);
xhttp.send();
}
值得注意的是,“内容长度”不是估计的长度,它必须是精确的长度,太短,浏览器会切断下载,太长,浏览器会认为下载失败。@ChrisChilvers这意味着PHP文件可能无法正确计算,对吗?@nicematt在那个例子中,它来自一个文件就可以了,但是如果你是流式传输zip条带
function updateProgress(evt)
{
if (evt.lengthComputable)
{ // evt.loaded the bytes the browser received
// evt.total the total bytes set by the header
// jQuery UI progress bar to show the progress on screen
var percentComplete = (evt.loaded / evt.total) * 100;
$('#progressbar').progressbar( "option", "value", percentComplete );
}
}
function sendreq(evt)
{
var req = new XMLHttpRequest();
$('#progressbar').progressbar();
req.onprogress = updateProgress;
req.open('GET', 'test.php', true);
req.onreadystatechange = function (aEvt) {
if (req.readyState == 4)
{
//run any callback here
}
};
req.send();
}