带有gzip压缩内容的XMLHttpRequest进度事件问题(FireFox除外)

时间:2016-03-14 10:45:48

标签: javascript json google-chrome xmlhttprequest progress-bar

在我的应用程序中,我使用XMLHttpRequest API请求大型JSON文件。这按预期工作。

我想在用户等待时显示进度条。一些JSON文件介于6到10Mb之间,因此进度条有助于改善整体体验。

这是我正在做的一个例子:

var progress = document.getElementById('progress');

function getData(url) {
    var req = new XMLHttpRequest();

  req.onprogress = function(event) {
    if (event.lengthComputable) {
      progress.value = event.loaded / event.total * 100;
    } else {
      console.log('lengthComputable failed');
    }
  }

  req.onload = function() {
    console.log('Finished loading');
    // ... handle data
  }

  req.open('GET', url, true);
  req.overrideMimeType('application/json');
  req.send(null);
}

getData('https://raw.githubusercontent.com/datasets/geo-countries/master/data/countries.geojson');

同样在jsfiddle上:https://jsfiddle.net/ctL5f73s/1/

如果内容未被gzip压缩,则进度条似乎在我到目前为止测试的所有浏览器上都能正常工作。但是如果服务器将其作为gzip发送,则只有firefox可以工作。

对于上下文,我从GitHub请求数据。我理解的是,他们将所有资产都用作gzip,我无法控制它。

我也知道XHR's progress events should handle gzipped content。 他们说的大部分内容都飞到了我的头上,但我收集到的是,当内容被压缩时,没有计划改变处理lengthComputable的方式。

Response Headers上,我看到Content-EncodingContent-Length是正确的:

enter image description here

问题是:有没有办法让进度事件在FireFox以外的浏览器上使用gzip内容?

如果不可能,有人能指出我的替代方案吗?最好是原生JS而不是库。

我不介意兼容​​性太远,但如果它不适用于最新版本的Chrome,那么这是一个问题。

2 个答案:

答案 0 :(得分:4)

我做了这样的事。这不是确切的,但它已经足够了。

req.onprogress = function(event) {
  if (event.lengthComputable) {
    progress.value = event.loaded / event.total * 100
  } else {
    var total = req.getResponseHeader('content-length')
    var encoding = req.getResponseHeader('content-encoding')
    if (total && encoding && (encoding.indexOf('gzip') > -1)) {
      // assuming average gzip compression ratio to be 25%
      total *= 4 // original size / compressed size
      progress.value = Math.min(100, event.loaded / total * 100)
    } else {
      console.log('lengthComputable failed')
    }
  }
}

显然,有时候进度会上升到100%,有时它会停留在100%,但只是暂时,所以很难说明。

答案 1 :(得分:0)

问题可能是您的Content-Type:text / plain。在shell命令行使用curl来获取GET(没有 - 压缩,立即看到二进制输出) - 响应是否立即显示?

例如,Chrome就没有立即针对'text / plain'点击onprogress回调,但是如果你使用'application / json'就行了。在您的回复标题中尝试'Content-Type:application / json',看看是否会产生影响。