【问题标题】:XMLHttpRequest Level 2 - Determinate if upload finishedXMLHttpRequest Level 2 - 确定上传是否完成
【发布时间】:2013-03-03 08:28:29
【问题描述】:

我正在使用 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 开始处理文件

还有其他可能检查这个吗?

【问题讨论】:

    标签: javascript ajax upload xmlhttprequest


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        您要收听的事件是 XHR 对象上的 readystatechange(而不是 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.
              }
            });
        

        【讨论】:

        • 但我不想检查连接是否关闭,因为上传完成后,PHP 会检查文件,这大约需要 . 10 秒并返回一些 JSON。当 PHP 开始检查文件时(=上传完成时),进度条应该切换到 indeterminated
        • 当文件完成传输时,loadend/load 事件触发,当您的脚本完成检查文件时(即 PHP 关闭连接时)readystatechange 事件触发 @987654333 @。因此,出于您的目的,在readystatechange 事件中将进度条切换到indeterminated。见:gist.github.com/anonymous/5208652
        • 不起作用。这是我的 JS:gist.github.com/anonymous/2a2fef447399a3b8e734 想象一下 PHP 脚本只是 sleep(10);。现在我想在这 10 秒内显示indeterminated 进度条
        • 您可能遇到了浏览器问题。我刚刚在 Chrome 25.0.1364.172 和 27.0.1449.0 上对其进行了测试(通过一些语法修复等),它按预期工作。但是,FF 19.0.2 正在同时触发 load/loadend/readyState 4
        • 确保将监听器添加到上传属性,而不是直接添加 xhr。
        【解决方案4】:

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

        您是否考虑过使用math.round 而不是math.ceil 代替var percent,这样您就有点模糊,这有助于减少几个百分点?

        您还应该为 loadComplete 添加另一个侦听器,如果您的 UI 卡在

        //only fires once
        xhr.addEventListener('loadend', uploadComplete, false);
        function uploadComplete(event) {
            console.log('rejoice...for I have completed');
            //do stuff
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-05-27
          • 2017-01-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-01-19
          • 2020-02-06
          • 1970-01-01
          相关资源
          最近更新 更多