2012-06-27 27 views
0

我想使用XHR對象的「progress」事件來獲取下載進度。如何正確編寫http響應以便使用XHR進度事件監聽器

下面是MDN

var req = new XMLHttpRequest(); 

req.addEventListener("progress", updateProgress, false); 
req.addEventListener("load", transferComplete, false); 
req.addEventListener("error", transferFailed, false); 
req.addEventListener("abort", transferCanceled, false); 

req.open(); 

... 

// progress on transfers from the server to the client (downloads) 
function updateProgress(evt) { 
    if (evt.lengthComputable) { 
    var percentComplete = evt.loaded/evt.total; 
    ... 
    } else { 
    // Unable to compute progress information since the total size is unknown 
    } 
} 

function transferComplete(evt) { 
    alert("The transfer is complete."); 
} 

function transferFailed(evt) { 
    alert("An error occurred while transferring the file."); 
} 

function transferCanceled(evt) { 
    alert("The transfer has been canceled by the user."); 
} 

我寫類似的代碼示例代碼,但進度事件的lengthComputable領域被證明是假的。 loaded字段是一些有限值,但total設置爲零。

從上面代碼示例的註釋中,我可以看到瀏覽器在HTTP響應中沒有獲得足夠的信息來計算有意義的下載進度。

什麼是編寫響應的正確方法來完成這項工作?我在測試中看到的回覆有Transfer-encoding: chunkedContent-Length: 8。我從Tornado Web服務器生成它。

回答

3

chunked transfer encoding中,響應的總長度不是由服務器指示的,因此不提前由客戶知道。

你可以嘗試兩件事。

  • Content-Length或者禁用分塊傳輸編碼爲正常方法。這就是Progress Events規範requires。但是我不知道Tornado是否可以這樣做。
  • 或者,在自定義響應標題中包含總長度,如X-Total-Length。然後,使用這樣的代碼,以確定您的百分比:

    function updateProgress(evt) { 
        var total = evt.lengthComputable ? 
           evt.total : parseInt(req.getResponseHeader('X-Total-Length')); 
        if (total) { 
        var percentComplete = evt.loaded/total; 
        // ... 
        } 
    } 
    
+0

第二招工作就好了。 – Jayesh

+0

第二個竅門工作有點。我需要這樣做是因爲gzip壓縮。 gzip總是使lengthComputable == false,Content-Length頭對於壓縮大小是正確的,並允許加載頁面。我必須近似壓縮級別並相應地調整總量。希望有更好的方法來做到這一點。 – Hobbes