在我的应用程序中,我使用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-Encoding
和Content-Length
是正确的:
问题是:有没有办法让进度事件在FireFox以外的浏览器上使用gzip内容?
如果不可能,有人能指出我的替代方案吗?最好是原生JS而不是库。
我不介意兼容性太远,但如果它不适用于最新版本的Chrome,那么这是一个问题。
答案 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',看看是否会产生影响。