Búsqueda de sitios web

javascript - Cómo obtener el progreso de XMLHttpRequest


¿Es posible obtener el progreso de un XMLHttpRequest (bytes subidos, bytes descargados)?

Esto sería útil para mostrar una barra de progreso cuando el usuario está subiendo un archivo grande. La API estándar no parece permitirlo, pero ¿quizás hay alguna extensión no estándar en alguno de los navegadores disponibles? Después de todo, parece una característica bastante obvia de tener, ya que el cliente sabe cuántos bytes se han subido/descargado.

nota: estoy al tanto de la alternativa de "consultar al servidor por el progreso" (es lo que estoy haciendo ahora mismo). El problema principal con esto (aparte del código complicado del lado del servidor) es que, típicamente, mientras se sube un archivo grande, la conexión del usuario está completamente saturada, porque la mayoría de los proveedores de servicios de Internet ofrecen poca velocidad de subida. Así que hacer solicitudes adicionales no es tan rápido como esperaba. Esperaba que hubiera una manera (quizás no estándar) de obtener esta información, que el navegador tiene en todo momento.

Respuesta #1

Para los bytes subidos es bastante fácil. Solo hay que monitorear el evento xhr.upload.onprogress. El navegador conoce el tamaño de los archivos que tiene que subir y el tamaño de los datos subidos, por lo que puede proporcionar la información de progreso.

Para los bytes descargados (al obtener la información con xhr.responseText), es un poco más difícil, porque el navegador no sabe cuántos bytes serán enviados en la solicitud al servidor. Lo único que el navegador sabe en este caso es el tamaño de los bytes que está recibiendo.

Hay una solución para esto, es suficiente establecer un encabezado Content-Length en el script del servidor, con el fin de obtener el tamaño total de los bytes que el navegador va a recibir.

Para más información, visita https://developer.mozilla.org/en/Using_XMLHttpRequest .

Ejemplo: Mi script del servidor lee un archivo zip (toma 5 segundos):

$filesize=filesize('test.zip');

header("Content-Length: " . $filesize); // set header length
// if the headers is not set then the evt.loaded will be 0
readfile('test.zip');
exit 0;

Ahora puedo monitorear el proceso de descarga del script del servidor, porque sé su longitud total:

function updateProgress(evt) 
{
   if (evt.lengthComputable) 
   {  // evt.loaded the bytes the browser received
      // evt.total the total bytes set by the header
      // jQuery UI progress bar to show the progress on screen
     var percentComplete = (evt.loaded / evt.total) * 100;  
     $('#progressbar').progressbar( "option", "value", percentComplete );
   } 
}   
function sendreq(evt) 
{  
    var req = new XMLHttpRequest(); 
    $('#progressbar').progressbar();    
    req.onprogress = updateProgress;
    req.open('GET', 'test.php', true);  
    req.onreadystatechange = function (aEvt) {  
        if (req.readyState == 4) 
        {  
             //run any callback here
        }  
    };  
    req.send(); 
}

Respuesta #2

Firefox soporta los eventos de progreso de descarga XHR.

EDICIÓN 2021-07-08 10:30 PDT

El enlace anterior está muerto. Hacer una búsqueda en el sitio WebDev de Mozilla dio como resultado el siguiente enlace:

https://developer.mozilla.org/es/docs/Web/API/ProgressEvent

Describe cómo usar el evento de progreso con XMLHttpRequest y proporciona un ejemplo. He incluido el ejemplo a continuación:

var progressBar = document.getElementById("p"),
    client = new XMLHttpRequest()
client.open("GET", "magical-unicorns")
client.onprogress = function(pe) {
  if(pe.lengthComputable) {
    progressBar.max = pe.total
    progressBar.value = pe.loaded
  }
}
client.onloadend = function(pe) {
  progressBar.value = pe.loaded
}
client.send()

También encontré este enlace, que es a lo que creo que apuntaba el enlace original.

https://developer.mozilla.org/es/docs/Web/API/XMLHttpRequest/progress_event

Artículos relacionados