xhr open example ejemplo javascript ajax progress-bar

javascript - open - xmlhttprequest json



Cómo obtener progreso desde XMLHttpRequest (8)

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

Esto sería útil para mostrar una barra de progreso cuando el usuario está cargando un archivo grande. La API estándar no parece ser compatible, pero tal vez hay alguna extensión no estándar en cualquiera de los navegadores que hay. Después de todo, parece una característica bastante obvia, ya que el cliente sabe cuántos bytes se cargaron / descargaron.

Nota: Conozco la alternativa "sondear al servidor para el progreso" (es lo que estoy haciendo en este momento). El principal problema con esto (aparte del complicado código del lado del servidor) es que, típicamente, mientras se carga un archivo grande, la conexión del usuario es completamente regada, porque la mayoría de los ISP ofrecen un flujo ascendente pobre. Así que hacer solicitudes adicionales no es tan receptivo como esperaba. Esperaba que hubiera una manera (quizás no estándar) de obtener esta información, que el navegador tiene en todo momento.


Aquí hay una agradable discusión del Indicador de progreso para el patrón AJAX:

http://ajaxpatterns.org/Progress_Indicator

Uno de los enfoques más prometedores parece ser la apertura de un segundo canal de comunicación de vuelta al servidor para preguntarle cuánto de la transferencia se ha completado.



La única forma de hacerlo con javascript puro es implementar algún tipo de mecanismo de sondeo. Tendrá que enviar solicitudes ajax a intervalos fijos (cada 5 segundos, por ejemplo) para obtener la cantidad de bytes recibidos por el servidor.

Una forma más eficiente sería usar flash. El componente flexible FileReference envía periódicamente un evento ''progress'' que contiene la cantidad de bytes ya cargados. Si necesita seguir con javascript, los puentes están disponibles entre actionscript y javascript. La buena noticia es que este trabajo ya ha sido hecho para ti :)

swfupload

Esta biblioteca permite registrar un controlador de Javascript en el evento de progreso de flash.

Esta solución tiene la gran ventaja de no requerir recursos adicionales en el lado del servidor.


Para el total de carga no parece haber una manera de manejar eso, pero hay algo similar a lo que desea descargar. Una vez que readyState es 3, puede consultar responseText periódicamente para obtener todo el contenido descargado hasta ahora como String (esto no funciona en IE), hasta que todo esté disponible y en ese punto pasará a readyState 4. El total los bytes descargados en cualquier momento dado serán iguales al total de bytes en la cadena almacenada en responseText.

Para un acercamiento total o nulo a la pregunta de carga, dado que tiene que pasar una cadena para cargar (y es posible determinar el total de bytes), el total de bytes enviados para readyState 0 y 1 será 0 y el total para readyState 2 serán los bytes totales en la cadena que pasó. El total de bytes enviados y recibidos en readyState 3 y 4 será la suma de los bytes en la cadena original más el total de bytes en responseText.


Si tiene acceso a su instalación de Apache y confía en un código de terceros, puede usar el módulo de progreso de carga de apache (si usa apache, también hay un módulo de progreso de carga nginx ).

De lo contrario, tendrías que escribir un guión al que puedas golpear fuera de banda para solicitar el estado del archivo (verificando el tamaño del archivo tmp, por ejemplo).

Hay algo de trabajo en Firefox 3, creo que para agregar soporte de progreso de carga para el navegador, pero eso no va a entrar en todos los navegadores y será ampliamente adoptado por un tiempo (más pena).



Para los bytes cargados es bastante fácil. Simplemente monitoree el evento xhr.upload.onprogress . El navegador conoce el tamaño de los archivos que debe cargar y el tamaño de los datos cargados, de modo 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 se enviarán en la solicitud del servidor. Lo único que sabe el navegador 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, para obtener el tamaño total de los bytes que el navegador va a recibir.

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

Ejemplo: Mi script de servidor lee un archivo zip (tarda 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é que es la 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(); }


<!DOCTYPE html> <html> <body> <p id="demo">result</p> <button type="button" onclick="get_post_ajax();">Change Content</button> <script type="text/javascript"> function update_progress(e) { if (e.lengthComputable) { var percentage = Math.round((e.loaded/e.total)*100); console.log("percent " + percentage + ''%'' ); } else { console.log("Unable to compute progress information since the total size is unknown"); } } function transfer_complete(e){console.log("The transfer is complete.");} function transfer_failed(e){console.log("An error occurred while transferring the file.");} function transfer_canceled(e){console.log("The transfer has been canceled by the user.");} function get_post_ajax() { var xhttp; if (window.XMLHttpRequest){xhttp = new XMLHttpRequest();}//code for modern browsers} else{xhttp = new ActiveXObject("Microsoft.XMLHTTP");}// code for IE6, IE5 xhttp.onprogress = update_progress; xhttp.addEventListener("load", transfer_complete, false); xhttp.addEventListener("error", transfer_failed, false); xhttp.addEventListener("abort", transfer_canceled, false); xhttp.onreadystatechange = function() { if (xhttp.readyState == 4 && xhttp.status == 200) { document.getElementById("demo").innerHTML = xhttp.responseText; } }; xhttp.open("GET", "http://it-tu.com/ajax_test.php", true); xhttp.send(); } </script> </body> </html>