我正在使用ajax进行文件上传。
上传文件后,php应该检查它(哑剧,大小,病毒(clamscan)等) - 对于较大的文件,这需要几秒钟。当文件上传时,HTML5 <progress>
正在填充,当文件准备好并且PHP开始检查时,进度应该切换为不确定。我想到了这样做的方法(它们都不工作):
检查upload.onload事件
xhr.upload.addEventListener("load", function (e) {
$("#uploadprogress").attr("value", false);
$("#uploadprogress").attr("max", false);
$("#progress").text("Checking file...");
});
这不起作用,因为onload
- 事件在请求准备就绪时会激活,而不是在上传准备好时。
检查上传进度百分比= 100%
xhr.upload.addEventListener("progress", function (e) {
if (e.lengthComputable && e) {
p = (e.loaded / e.total);
if (p==1) {
$("#uploadprogress").attr("value", false);
$("#uploadprogress").attr("max", false);
$("#progress").text("Checking file...");
} else {
var percent = Math.ceil(p * 1000) / 10;
$("#uploadprogress").val(e.loaded);
$("#uploadprogress").attr("max", e.total);
$("#progress").text("Uploading... " + percent + "%");
}
}
}
});
这不起作用,因为上传百分比有时会停在大约。 97%,尽管上传完成并且PHP开始处理文件
是否有另一种可能性来检查这个?
答案 0 :(得分:51)
您想要侦听的事件是XHR对象上的readystatechange
(不在XHR.upload上)。当上传完成并 服务器关闭连接时,readyState
为4
。无论服务器是否关闭连接,上传完成后都会触发loadend
/ load
。仅供参考,以下是您可以收听的事件以及何时开火:
var xhr = new XMLHttpRequest();
// ...
// do stuff with xhr
// ...
xhr.upload.addEventListener('loadstart', function(e) {
// When the request starts.
});
xhr.upload.addEventListener('progress', function(e) {
// While sending and loading data.
});
xhr.upload.addEventListener('load', function(e) {
// When the request has *successfully* completed.
// Even if the server hasn't responded that it finished.
});
xhr.upload.addEventListener('loadend', function(e) {
// When the request has completed (either in success or failure).
// Just like 'load', even if the server hasn't
// responded that it finished processing the request.
});
xhr.upload.addEventListener('error', function(e) {
// When the request has failed.
});
xhr.upload.addEventListener('abort', function(e) {
// When the request has been aborted.
// For instance, by invoking the abort() method.
});
xhr.upload.addEventListener('timeout', function(e) {
// When the author specified timeout has passed
// before the request could complete.
});
// notice that the event handler is on xhr and not xhr.upload
xhr.addEventListener('readystatechange', function(e) {
if( this.readyState === 4 ) {
// the transfer has completed and the server closed the connection.
}
});
答案 1 :(得分:2)
基于https://bugzilla.mozilla.org/show_bug.cgi?id=637002。
让我们来看一个完整的工作示例...
// YOUR (SIMPLE) JAVASCRIPT FILE
var form = new FormData(), xhr = new XMLHttpRequest();
form.append('inputname', YOURFILE);
xhr.open('POST', 'http://oneserver/onephpfile', true);
xhr.setRequestHeader('X-CSRF-Token', 'somestring');
xhr.onreadystatechange = function () {
if ((xhr.readyState === 4) && (xhr.status === 200))
// do other thing with xhr.responseText.trim()
};
xhr.upload.addEventListener('loadstart', showProgressBarFunction, false);
xhr.upload.addEventListener('progress', updateProgressBarFunction, false);
xhr.upload.addEventListener('load', updateProgressBarFunction, false);
xhr.send(form);
// YOUR FIRST (SIMPLE) PHP FILE
header('Content-Type: text/plain; charset=utf-8');
header('Cache-Control: no-cache, must-revalidate');
sleep(20);
echo 'file processing ended';
使用第一个PHP文件,您将看到: 10%... 50%... 75%...&#39;使用Firefox做其他事情&#39; (4 / 10/28/32)和IE(10/11)。 然而你会看到: 10%...... 50%...... 75%...... 100%......&#39;做其他事情&#39; 使用Chrome / Chromium(33/37)和Opera(24)。
// YOUR SECOND (SIMPLE) PHP FILE
header('Content-Encoding: chunked', true);
header('Content-Type: text/plain; charset=utf-8');
header('Cache-Control: no-cache, must-revalidate');
ini_set('output_buffering', false);
ini_set('implicit_flush', true);
ob_implicit_flush(true);
for ($i = 0; $i < ob_get_level(); $i++)
ob_end_clean();
echo ' ';
sleep(20);
echo 'file processing ended';
使用第二个PHP文件,您将看到: 10%... 50%... 75%... 100%...&#39;做其他事情&#39; Chrome / Chromium(33/37/53),Opera(24/42),Firefox(4/10/28/32/45),IE(10/11)和Edge(14)!
答案 2 :(得分:1)
这是hTML5规范的一个相对已知的垮台,当他们可以轻松扩展它以添加timeRemaining和transferSpeed等信息时。
您是否考虑过使用math.round
代替math.ceil
var percent
,这样您就会陷入一些模糊状态,这有助于绕过几个百分点?
你应该为loadComplete添加另一个监听器,如果你的UI保持在&lt; 100%,即使它在后端完成了:
//only fires once
xhr.addEventListener('loadend', uploadComplete, false);
function uploadComplete(event) {
console.log('rejoice...for I have completed');
//do stuff
}
答案 3 :(得分:0)
检查readyState,if(readyState==4) {//it has finished, put code here}