XMLHttpRequest Level 2 - Определить, завершена ли загрузка
Я использую ajax для загрузки файлов.
После загрузки файла php должен проверить его (mime, size, virus (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
-event firest, когда запрос готов, а не когда загрузка готова.
Проверка, если процент выполнения загрузки = 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 начинает обрабатывать файлы
Есть ли еще возможность проверить это?
Ответы
Ответ 1
Событие, которое вы хотите прослушать, 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.
}
});
Ответ 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%... "делают что-то другое" с 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';
С этим вторым файлом PHP вы увидите: 10%... 50%... 75%... 100%... "делайте другое" с Chrome/Chromium (33/37/53), Opera (24/42), Firefox (4/10/28/32/45), IE (10/11) и Edge (14)!
Ответ 3
Это относительно известное падение спецификации hTML5, когда они могли легко расширить его, чтобы добавить информацию, такую как timeRemaining и transferSpeed.
Считаете ли вы использование math.round
вместо math.ceil
для var percent
, чтобы вы выпекали немного нечеткости, что помогло бы обойти несколько% очков?
Вы также должны добавить еще один прослушиватель для loadComplete, если вы получаете UI, застрявший на < 100%, даже если он завершен на бэкэнд:
//only fires once
xhr.addEventListener('loadend', uploadComplete, false);
function uploadComplete(event) {
console.log('rejoice...for I have completed');
//do stuff
}
Ответ 4
Проверьте состояние readyState, if(readyState==4) {//it has finished, put code here}