Подтвердить что ты не робот

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 начинает обрабатывать файлы

Есть ли еще возможность проверить это?

4b9b3361

Ответ 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}