Javascript 为什么ProgressEvent.LengthComputeable为false?
我正在Google Chrome、Safari和Firefox中使用XMLHttpRequest加载一个JSON文件。在所有三个浏览器中,我都会收到正确显示Javascript 为什么ProgressEvent.LengthComputeable为false?,javascript,xmlhttprequest,Javascript,Xmlhttprequest,我正在Google Chrome、Safari和Firefox中使用XMLHttpRequest加载一个JSON文件。在所有三个浏览器中,我都会收到正确显示.loaded属性的ProgressEvents。但是,.lengthComputeable属性为false,.total属性为零。我已经检查了内容长度HTTP头是否正在发送,并且是否正确-它是正确的。响应正在进行gzip编码,但内容长度正确显示了编码长度(在解压缩之前) 为什么总长度在myProgressEvents中不可用 以下是标题:
.loaded
属性的ProgressEvent
s。但是,.lengthComputeable
属性为false,.total
属性为零。我已经检查了内容长度
HTTP头是否正在发送,并且是否正确-它是正确的。响应正在进行gzip编码,但内容长度
正确显示了编码长度(在解压缩之前)
为什么总长度在myProgressEvent
s中不可用
以下是标题:
HTTP/1.1 200 OK
ETag: "hKXdZA"
Date: Wed, 20 Jun 2012 20:17:17 GMT
Expires: Wed, 20 Jun 2012 20:17:17 GMT
Cache-Control: private, max-age=3600
X-AppEngine-Estimated-CPM-US-Dollars: $0.000108
X-AppEngine-Resource-Usage: ms=2 cpu_ms=0 api_cpu_ms=0
Content-Type: application/json
Content-Encoding: gzip
Server: Google Frontend
Content-Length: 621606
注意:该文件是通过谷歌应用程序引擎提供的
下面是JavaScript:
var req;
if (window.XMLHttpRequest){
req = new XMLHttpRequest();
if(req.overrideMimeType){
req.overrideMimeType( "text/json" );
}
}else{
req = new ActiveXObject('Microsoft.XMLHTTP');
}
// Listen for progress events
req.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);
req.open('GET', this.url);
注意:该代码中的
控制台.log
显示了数百个最新加载的事件,但是.lengthComputeable
始终为false,并且总数始终为零self
指负责此XMLHttpRequest
的对象。如果在XMLHttpRequestProgressEvent中LengthComputeable为false,则表示服务器从未在响应中发送内容长度头
如果您使用nginx作为代理服务器,这可能是罪魁祸首,特别是如果它没有将内容长度头从上游服务器通过代理服务器传递到浏览器。使用req.upload.addEventListener进行上传
req.addEventListener event.LengthComputeable将始终为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);
与此同时,Firefox的一切都很好,但Chrome没有显示gzip内容的进展
如果加载的
和总计
指的是压缩或未压缩的内容,则这似乎是由于规格不明确造成的。2014年6月26日,明确他们应参考传输(压缩)内容:
6.1。使用ProgressEvent
界面触发事件
[…]给定已传输和长度[…]触发事件[…]ProgressEvent
,将加载的
属性初始化为已传输,如果长度不为0,则将长度可计算的
属性初始化为true,将总计
属性初始化为length
然而,2015年Chromium bug报告解释说情况有所不同,并指出:
编码时,total
保持为0,并且未设置lengthComputeable
事件本身仍被激发,并且仍填充event.loaded
。但是Chrome正在动态解压缩gzip的内容,并且(今天)将加载的设置为结果解压缩长度,而不是传输长度。这无法与内容长度
标题的值进行比较,因为这是压缩内容的长度,因此加载的
将大于内容长度
充其量可以假设一些压缩因子来比较加载的与内容长度,或者让服务器添加一些自定义头来提供原始长度或真实压缩因子,假设Chrome的动态解压缩不会改变
我不知道Chrome对PHP或apache/nginx中设置的内容编码的其他值做了什么
header("Content-Encoding: none");
问题已解决。在控制器代码中设置内容长度。这将设置事件。长度可计算
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 + '%';
}
};
我们可以看到您查看这些数据的javascript代码吗?您是否尝试过在非google应用程序引擎服务器上使用这些代码?如果lengthComputeable
为false,则xhr对象不知道文件的长度。我们在这里使用GAE,但它的大部分功能都存在大量问题——这并不奇怪。我尝试过另一台服务器,但它给了我分块编码,因此没有内容长度。在本例中,LengthComputeable==false是有意义的。我以后还要试另一个。在我看来,GAE的行为是由标题决定的,但我和你一样怀疑它。看看它的兼容性:我已经看到了req.addEventListener
事件。LengthComputeable
也应该是真的。对于大型请求,这似乎是错误的:我尝试的是10MB JPG。我没有做过广泛的测试,但你可能是对的,req.upload
的lengthComputeable
更经常是正确的……但正如名字所暗示的那样:这是用于从浏览器到服务器的上传,而不是从服务器到浏览器的下载。如果你设置了一个被忽略的内容长度头,您还必须设置响应的缓冲区大小,以便能够容纳正在发送的字节。否则,在HTTP 1.1中,它将恢复为对响应进行分块。或者,许多年后,在Chrome中使用gzip的内容时,即使设置了正确的头:-(至少:我假设event.loaded
的值是解压缩的大小(而不是传输的长度)与。。。