2012-06-20 27 views
15

Estoy cargando un archivo JSON utilizando XMLHttpRequest en Google Chrome, Safari y Firefox. En los tres buscadores recibo ProgressEvent s que muestran correctamente la propiedad .loaded. Sin embargo, la propiedad .lengthComputable es falsa y la propiedad .total es cero. He comprobado que el encabezado HTTP Content-Length se está enviando y es correcto, lo es. La respuesta está siendo codificada por gzip, pero el Content-length muestra correctamente la longitud codificada (antes de la descompresión).¿Por qué es falso ProgressEvent.lengthComputable?

¿Por qué la longitud total no estaría disponible en mi ProgressEvent s?

Éstos son los encabezados:

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 

Nota: el archivo está siendo servida a través de Google App Engine.

Aquí está el código 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); 

Nota: El console.log en ese código está mostrando cientos de eventos con hasta la fecha .loaded s .lengthComputable pero siempre es falsa y .total es siempre cero. self se refiere al objeto responsable de este XMLHttpRequest.

+1

¿Podemos ver el código javascript que tiene que está viendo esta información? – tkone

+0

Lo he agregado ahora. –

+1

¿Has intentado usar esto en un servidor de motor de aplicación que no es de Google? Si 'lengthComputable' es falso que el objeto xhr no sabe cuánto tiempo está el archivo. Utilizamos GAE aquí y tenemos problemas enormes con la mayor parte de su funcionalidad; esto no sería sorprendente. – tkone

Respuesta

14

Si lengthComputable es falso dentro de XMLHttpRequestProgressEvent, eso significa que el servidor nunca envió un encabezado Content-Length en la respuesta.

Si está utilizando nginx como un servidor proxy, este podría ser el culpable, especialmente si no está pasando el encabezado Content-Length desde el servidor ascendente a través del servidor proxy al navegador.

+0

Si está configurando un encabezado de longitud de contenido que se está ignorando, también debe establecer el tamaño del búfer de su respuesta para poder retener los bytes que está enviando. De lo contrario, en HTTP 1.1 volverá a fragmentar la respuesta. –

+0

O, muchos años después, cuando se utiliza contenido gzip en Chrome, incluso cuando se han configurado los encabezados correctos. :-( – Arjan

1

uso req.upload.addEventListener para la carga

req.addEventListener event.lengthComputable siempre será falsa

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

He visto que el 'req.addEventListener'' event.lengthComputable' también es verdadero. Parece ser falso para solicitudes grandes: el que probé era un JPG de 10MB. No he hecho pruebas extensas, pero es posible que tengas razón de que 'req.upload'' lengthComputable' es cierto más a menudo. – trysis

+1

... pero como su nombre indica: eso es para las cargas de un navegador a otro, no para las descargas de un servidor a otro. – Arjan

1

Entretanto 2017, las cosas están bien en Firefox, pero no lo hace Chrome mostrar el progreso del contenido gzip'd

Esto parece ser causado por las especificaciones, una vez que no está claro si loaded y total se refieren al contenido comprimido o no comprimido. Since 26 de junio 2014 the XMLHttpRequest specifications maquillaje claro que deben referirse a los contenidos transmitidos (comprimido):

6,1. Disparando eventos utilizando la interfaz ProgressEvent

[...] dada transmitida y longitud [...] desencadenar un evento [...] ProgressEvent, con el atributo loaded inicializado a transmitido, y si longitud no es 0, con el atributo lengthComputable inicializado en true y el atributo total inicializado en longitud.

Sin embargo, el 2015 Cromo informe de error "XHR's progress events should handle gzipped content" explica que las cosas eran diferentes, y afirma:

cuando se codifica, total estancias a ser 0 y lengthComputable no se ha establecido

El evento sí mismo todavía se enciende, y event.loaded todavía se llena. Pero Chrome está descomprimiendo el contenido gzip'd sobre la marcha y (hoy) establece loaded en la longitud descomprimida resultante, no en la transmitida de longitud. No se puede comparar con el valor del encabezado Content-Length, ya que esa es la longitud del contenido comprimido , por lo que loaded será mayor que la longitud del contenido.

A lo sumo se podría suponer algún factor de compresión para comparar loaded contra Content-Length, o hacer que el servidor de añadir un poco de cabecera personalizada para proporcionar la longitud original o el verdadero factor de compresión, asumiendo Chrome en la marcha de descompresión no va a cambiar.

No tengo idea de qué hace Chrome para otros valores para Content-Encoding.

+0

Por lo menos: Supongo que el valor de 'event.loaded' es el tamaño descomprimido (en lugar de la longitud transmitida) no está relacionado con https: //crbug.com/763700 ... – Arjan

Cuestiones relacionadas