Why is ProgressEvent.lengthComputable false?

后端 未结 5 614
难免孤独
难免孤独 2020-12-03 08:02

I am loading a JSON file using XMLHttpRequest in Google Chrome, Safari and Firefox. In all three browsers I am receiving ProgressEvents which correctly show the

相关标签:
5条回答
  • 2020-12-03 08:08

    Set the Content-Length in the controller code. This will set the event.lengthComputable.

    var fileSize = new FileInfo(filePathAbs).Length;
    context.Response.AddHeader("Content-Length", fileSize.ToString());
    context.Response.AddHeader("content-disposition", "inline;filename=" + fileName);
    
    var req = new XMLHttpRequest();
    
    req.open('GET', '/EReader/GetDocument?p=@Model.EncodedTempFilePath');
    req.responseType = "arraybuffer";
    req.onprogress = function (event) { 
        if (event.lengthComputable) {
            percentage = Math.floor(event.loaded * 100 / event.total); // give the percentage
            var elem = document.getElementById("bar");
            elem.style.width = percentage + '%';
        }
    };
    
    0 讨论(0)
  • 2020-12-03 08:22

    Just set in PHP or apache/nginx

    header("Content-Encoding: none");
    

    problem solved.

    0 讨论(0)
  • 2020-12-03 08:27

    use req.upload.addEventListener for upload

    req.addEventListener event.lengthComputable will always be false

    req.upload.addEventListener("progress", function (event) {
        console.log(event, event.lengthComputable, event.total);
        if (event.lengthComputable) {
            self.progress = event.loaded / event.total;
        } else if (this.explicitTotal) {
            self.progress = Math.min(1, event.loaded / self.explicitTotal);
        } else {
            self.progress = 0;
        }
        self.dispatchEvent(Breel.Asset.ON_PROGRESS);
    }, false);
    
    0 讨论(0)
  • 2020-12-03 08:31

    Meanwhile 2017, things are fine in Firefox, but Chrome does not show the progress for gzip'd content.

    This seems to be caused by the specifications once being unclear if loaded and total refer to the compressed or uncompressed content. Since Jun 26, 2014 the XMLHttpRequest specifications make clear they should refer to the transmitted (compressed) content:

    6.1. Firing events using the ProgressEvent interface

    [...] given transmitted and length [...] fire an event [...] ProgressEvent, with the loaded attribute initialized to transmitted, and if length is not 0, with the lengthComputable attribute initialized to true and the total attribute initialized to length.

    However, the 2015 Chromium bug report "XHR's progress events should handle gzipped content" explains that things were different, and states:

    when encoded, total stays to be 0 and lengthComputable is not set

    The event itself is still fired, and event.loaded is still populated. But Chrome is decompressing gzip'd content on the fly and (today) sets loaded to the resulting decompressed length, not to the transmitted length. This cannot be compared to the value of the Content-Length header, as that's the length of the compressed content, so loaded will become larger than the content length.

    At best one could assume some compression factor to compare loaded against Content-Length, or make the server add some custom header to provide the original length or the true compression factor, assuming Chrome's on-the-fly decompression will not change.

    I've no idea what Chrome does for other values for Content-Encoding.

    0 讨论(0)
  • 2020-12-03 08:33

    If lengthComputable is false within the XMLHttpRequestProgressEvent, that means the server never sent a Content-Length header in the response.

    If you're using nginx as a proxy server, this might be the culprit, especially if it's not passing the Content-Length header from the upstream server through the proxy server to the browser.

    0 讨论(0)
提交回复
热议问题