【问题标题】:XMLHttpRequest progress event issue with gzipped content (except FireFox)压缩内容的 XMLHttpRequest 进度事件问题(FireFox 除外)
【发布时间】:2016-06-29 08:47:20
【问题描述】:

在我的应用程序中,我使用 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 是正确的:

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

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

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

【问题讨论】:

  • 我很好奇 - 你得到这个答案了吗?
  • 不幸的是目前还没有。
  • 我们使用的另一种方法是在服务器端添加一个额外的标题:X-Uncompressed-Content-Length: ${file.length} 并在 javascript 端解析它。

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


【解决方案1】:

我做了这样的事情。不准确,但已经足够了。

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%,但只是很短的时间,所以几乎不会被注意到。

【讨论】:

    【解决方案2】:

    问题可能是您的 Content-Type: text/plain。在 shell 命令行中使用 curl 中的 GET(不带 --compressed,可以立即看到二进制输出) -- 响应会立即显示吗?

    例如,Chrome 不会立即触发“text/plain”的 onprogress 回调,但如果您使用“application/json”,它会立即触发。在您的响应标头中尝试“Content-Type: application/json”,看看是否会有所不同。

    【讨论】:

      猜你喜欢
      • 2017-01-21
      • 1970-01-01
      • 1970-01-01
      • 2010-10-23
      • 2013-06-16
      • 2021-07-31
      • 2011-04-18
      • 1970-01-01
      • 2013-11-17
      相关资源
      最近更新 更多