Subir Archivos
Para subir archivos mediante Ajax, debemos en un formulario crear un campo de tipo file y en nuestra rutina Ajax utilizar un objeto FormData con el cual recogeremos los datos para poder darles el formato necesario y hacer la subida de nuestro archivo al servidor.
El objeto FormData debe ser utilizado con cuidado ya que aún puede haber versiones de navegadores que no le dan soporte completamente, sin embargo es una solución bastante sólida.
Veamos en el siguiente código como hacer una subida de un archivo básica:
<!DOCTYPE HTML> <html> <head> <title>Example</title> <style> .table {display:table;} .row {display:table-row;} .cell {display: table-cell; padding: 5px;} .label {text-align: right;} </style> </head> <body> <form id="fruitform" method="post" action="http://titan:8080/form"> <div class="table"> <div class="row"> <div class="cell label">Bananas:</div> <div class="cell"><input name="bananas" value="2"/></div> </div> <div class="row"> <div class="cell label">Apples:</div> <div class="cell"><input name="apples" value="5"/></div> </div> <div class="row"> <div class="cell label">Cherries:</div> <div class="cell"><input name="cherries" value="20"/></div> </div> <div class="row"> <div class="cell label">File:</div> <div class="cell"><input type="file" name="file"/></div> </div> <div class="row"> <div class="cell label">Total:</div> <div id="results" class="cell">0 items</div> </div> </div> <button id="submit" type="submit">Submit Form</button> </form> <script> document.getElementById("submit").onclick = handleButtonPress; var httpRequest; function handleButtonPress(e) { e.preventDefault(); var form = document.getElementById("fruitform"); var formData = new FormData(form); httpRequest = new XMLHttpRequest(); httpRequest.onreadystatechange = handleResponse; httpRequest.open("POST", form.action); httpRequest.send(formData); } function handleResponse() { if (httpRequest.readyState == 4 && httpRequest.status == 200) { document.getElementById("results").innerHTML = httpRequest.responseText; } } </script> </body> </html>
Al momento de incorporar el input tipo file, el objeto FormData automáticamente hace las gestiones para que nuestro archivo pueda ser subido al servidor, en la siguiente imagen podemos ver como el navegador interpreta esto:
En este caso era una imagen bastante ligera por lo que el tiempo de carga del archivo al servidor no se nota, sin embargo si fuese un pdf de 30 MB el tiempo sería mucho mayor, como esto para el usuario es transparente, él podría pensar que la página no está “haciendo nada” o que se quedó “pensando” para evitar esto podemos incorporar una barra de progreso con lo cual el avance se hace visible.
Para lograr ver el progreso de la subida nos vamos a valer del objeto XMLHttpRequest para ir verificando el estado de la petición Ajax:
<!DOCTYPE HTML> <html> <head> <title>Example</title> <style> .table {display:table;} .row {display:table-row;} .cell {display: table-cell; padding: 5px;} .label {text-align: right;} </style> </head> <body> <form id="fruitform" method="post" action="http://titan:8080/form"> <div class="table"> <div class="row"> <div class="cell label">Bananas:</div> <div class="cell"><input name="bananas" value="2"/></div> </div> <div class="row"> <div class="cell label">Apples:</div> <div class="cell"><input name="apples" value="5"/></div> </div> <div class="row"> <div class="cell label">Cherries:</div> <div class="cell"><input name="cherries" value="20"/></div> </div> <div class="row"> <div class="cell label">File:</div> <div class="cell"><input type="file" name="file"/></div> </div> <div class="row"> <div class="cell label">Progress:</div> <div class="cell"><progress id="prog" value="0"/></div> </div> <div class="row"> <div class="cell label">Total:</div> <div id="results" class="cell">0 items</div> </div> </div> <button id="submit" type="submit">Submit Form</button> </form> <script> document.getElementById("submit").onclick = handleButtonPress; var httpRequest; function handleButtonPress(e) { e.preventDefault(); var form = document.getElementById("fruitform"); var progress = document.getElementById("prog"); var formData = new FormData(form); httpRequest = new XMLHttpRequest(); var upload = httpRequest.upload; upload.onprogress = function(e) { progress.max = e.total; progress.value = e.loaded; } upload.onload = function(e) { progress.value = 1; progress.max = 1; } httpRequest.onreadystatechange = handleResponse; httpRequest.open("POST", form.action); httpRequest.send(formData); } function handleResponse() { if (httpRequest.readyState == 4 && httpRequest.status == 200) { document.getElementById("results").innerHTML = httpRequest.responseText; } } </script> </body> </html>
Hemos definido un elemento progress y con el objeto XMLHttpRequest podemos ir asignando los valores mientras vaya progresando la subida, en el navegador lo podremos ver de la siguiente forma:
Podemos utilizar Ajax para mucho más que consultar elementos en otras páginas, también podemos usarlo para mejorar nuestros formularios a la hora de capturar datos.