javascript XMLHttpRequest 级别 2 - 确定上传是否完成
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15418608/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
XMLHttpRequest Level 2 - Determinate if upload finished
提问by ninov
I am using ajax for file uploads.
After the file is uploaded, php should check it (mime, size, virus (clamscan) and more) - this takes some seconds for larger files. While the file is uploading, a HTML5 <progress>
is filling, when the file is ready and PHP starts checking, the progress should switch to indeterminate. I thought of to ways to do this (which both do notwork):
我正在使用 ajax 进行文件上传。文件上传后,php 应该检查它(mime、大小、病毒(clamscan)等) - 对于较大的文件,这需要几秒钟。当文件上传时,HTML5<progress>
正在填充,当文件准备好并且 PHP 开始检查时,进度应该切换到不确定。我认为对的方式来做到这一点(这两者做不工作):
Checking upload.onload event
检查 upload.onload 事件
xhr.upload.addEventListener("load", function (e) {
$("#uploadprogress").attr("value", false);
$("#uploadprogress").attr("max", false);
$("#progress").text("Checking file...");
});
This doesn't work, because the onload
-event firest when the request is ready, not when upload is ready.
这不起作用,因为onload
-event 在请求准备好时触发,而不是在上传准备好时触发。
Checking if upload progress percentage = 100%
检查上传进度百分比是否 = 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 + "%");
}
}
}
});
This does not work, because the upload percentage sometimes stops at approx. 97%, despite the upload is finished and PHP starts handling the files
这不起作用,因为上传百分比有时会停止在大约。97%,尽管上传完成并且 PHP 开始处理文件
Is there another possibility checking this?
还有另一种可能性检查这个吗?
回答by zertosh
The event you want to listen to is readystatechange
on the XHR object (not on XHR.upload). readyState
is 4
when the upload has finished sending andthe server closes the connection. loadend
/load
fire when the upload has finished regardless of whether the server closes the connection. Just for reference, here are the events you can listen to and when they fire:
您要侦听的事件readystatechange
在 XHR 对象上(而不是在 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.
}
});
回答by luigifab
Based on https://bugzilla.mozilla.org/show_bug.cgi?id=637002.
基于https://bugzilla.mozilla.org/show_bug.cgi?id=637002。
Let's go for a complete working example...
让我们来看一个完整的工作示例......
// 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';
With this first PHP file, you will see: 10%... 50%... 75%... 'do other thing'with Firefox (4/10/28/32) and IE (10/11). Howeveryou we will see: 10%... 50%... 75%... 100%... 'do other thing'with Chrome/Chromium (33/37) and Opera (24).
使用第一个 PHP 文件,您将看到:10%... 50%... 75%...使用 Firefox (4/10/28/32) 和 IE (10/11) “做其他事情”。但是你会看到:10%... 50%... 75%... 100%...用 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';
With this second PHP file, you will see: 10%... 50%... 75%... 100%... 'do other thing'with Chrome/Chromium (33/37/53), Opera (24/42), Firefox (4/10/28/32/45), IE (10/11) and Edge (14)!
使用第二个 PHP 文件,您将看到:10%... 50%... 75%... 100%... 'do other thing'with Chrome/Chromium (33/37/53), Opera (24 /42)、Firefox (4/10/28/32/45)、IE (10/11) 和 Edge (14)!
回答by shadowstorm
This is a relatively known downfall of the hTML5 spec, when they could have easily extended it to add information such as timeRemaining and transferSpeed.
这是 hTML5 规范的一个相对众所周知的垮台,当时他们可以轻松地扩展它以添加诸如 timeRemaining 和 transferSpeed 之类的信息。
Have you considered using math.round
instead of math.ceil
for var percent
so that you are baking in a bit of fuzziness that would help get around a few % points being off?
你有没有考虑过使用math.round
而不是math.ceil
for 来var percent
让你在一些模糊的情况下烘焙,这将有助于解决几个百分点的问题?
You should also add another listener for loadComplete, if you are getting the UI stuck at <100% even though it is complete on the backend:
您还应该为 loadComplete 添加另一个侦听器,如果您的 UI 卡在 <100%,即使它在后端已完成:
//only fires once
xhr.addEventListener('loadend', uploadComplete, false);
function uploadComplete(event) {
console.log('rejoice...for I have completed');
//do stuff
}
回答by aIKid
Check the readyState, if(readyState==4) {//it has finished, put code here}
检查就绪状态, if(readyState==4) {//it has finished, put code here}