21

我正在使用 ajax 进行文件上传。文件上传后,php 应该检查它(mime、大小、病毒(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 在请求准备好时触发,而不是在上传准备好时触发。

检查上传进度百分比是否 = 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 开始处理文件

还有另一种可能性检查吗?

4

4 回答 4

55

您要收听的事件readystatechange在 XHR 对象上(而不是在 XHR.upload 上)。readyState4上传完成发送并且 服务器关闭连接的时间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.
      }
    });
于 2013-03-19T03:40:22.137 回答
3

基于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)!

于 2014-09-14T17:24:59.240 回答
1

这是 hTML5 规范的一个相对众所周知的失败,当时他们可以轻松地对其进行扩展以添加诸如 timeRemaining 和 transferSpeed 之类的信息。

您是否考虑过使用math.round而不是math.ceilforvar percent以便您在烘烤时有点模糊,这将有助于减少几个 % 的分数?

您还应该为 loadComplete 添加另一个侦听器,如果您的 UI 卡在 <100%,即使它在后端已完成:

//only fires once
xhr.addEventListener('loadend', uploadComplete, false);
function uploadComplete(event) {
    console.log('rejoice...for I have completed');
    //do stuff
}
于 2013-03-19T00:52:24.607 回答
0

检查就绪状态,if(readyState==4) {//it has finished, put code here}

于 2013-03-20T09:08:25.417 回答