Ajax fácil, tercera parte (Subir archivos al servidor)

Buenas, hoy continuaremos con este tercer post de ajax…. Bueno, en realidad, esto se podría decir que no es ajax. Verán, muchos al empezar a aprender ajax nos topamos con una columna de desilusión, en realidad ajax tiene una restricción: no permite enviar archivos al servidor.

Sin embargo, hay una forma de simular la subida de archivos al servidor sin tener que recargar la página. Aunque el título de este post diga «ajax» debo aclarar que acá no mostraré nada que tenga que ver con ajax como lo hice en: Ajax fácil, primera parte y Ajax fácil, segunda parte. Sí, soy un mentiroso, pero si llegaste hasta acá es porque querés saber cómo subir archivos al servidor y por eso creé este post.

Sin más palabrería, voy a explicarte de qué se tratará nuestro ejemplo.

Crearemos un campo de ingreso para subir archivos y un botón.
Al presionar ese botón el archivo se enviará al servidor.
Al subirse el archivo (o fallar la subida) se disparará una función javascript, pero todo eso sin recargar la página.

Bueno, por empezar tendrás que crear:

  • Un archivo donde se mostrará el formulario de subida de archivos, yo lo llamaré index.php.
  • Un archivo controlador donde se procesará el archivo en el servidor llamado subir_archivo.php.
  • Una carpeta donde se subirán los archivos, de nombre archivos.

En archivo index.php crearemos un formulario con cinco elementos de esta forma:

<form action="subir_archivo.php" method="post" 
enctype="multipart/form-data" target="contenedor_subir_archivo">
    <label> Archivo </label>
    <input type="file" name="archivo" />
    <input type="submit" id="boton_subir_archivo" />
    <div id="respuesta"></div>
    <iframe width="1" height="1" frameborder="0" name="contenedor_subir_archivo" style="display: none"></iframe>
</form>

Bueno, te explico para qué es cada cosa:

El form tendrá un atributo action con el controlador donde irá la petición y un method para indicar que el formulario se mandará por post. Hasta acá nada nuevo, a su vez habrá un atributo enctype que su valor será «multipart/form-data», esto le indicará al formulario que el envío contendrá archivos. Tal vez ya conozcas esto último, pero no está de mal repasarlo. El atributo target luego lo explicaré para qué será.

Luego habrá un elemento label, nada nuevo. Un input file, que indicará que con el mismo se cargarán archivos y un input submit, que será el botón que permitirá enviar el formulario. Y un div vacío que será el encargado de mostrar el mensaje de precarga y las respuestas del servidor.

Ahora, acá viene lo interesante, el protagonista del post, quien se encargue de que nuestra página no tenga que recargarse al enviar el archivo al servidor: un iframe. Quizás nunca hayas escuchado hablar de estos elementos o quizás sí, lo único que puedo decirte que es que la etiqueta iframe es una etiqueta de html que permite cargar el contenido de una página dentro de otra.

Lo que haremos será enviar el formulario desde index.php a subir_archivo.php, pero la página no se recargará, ya que con el atributo target que tendrá el valor del name del iframe le indicaremos que deberá cargarse dentro del iframe y de esta manera simularemos un envío de datos asincrónico al servidor. Además este iframe tendrá un style display: none para ocultar su contenido, que no le es de importancia al usuario.

(Importante: El valor del target del formulario, debe ser el mismo que el name del iframe)

Bueno, continuemos, dentro del archivo index.php crearemos tres funciones de javascript:

function cargando(){
    $("#respuesta").html('Cargando');
} 
function resultadoOk(){
    $("#respuesta").html('El archivo ha sido subido exitosamente.');
} 
function resultadoErroneo(){
    $("#respuesta").html('Ha surgido un error y no se ha podido subir el archivo.');
}
$(document).ready(function(){
    $("#boton_subir_archivo").click(function(){
       cargando();
    });
});

Nada del otro mundo, al presionarse el botón se disparará la función cargando() para mostrar que el archivo se envió a procesar. Dos funciones, resultadoOk() que se disparará si el archivo pudo ser movido a la carpeta archivos y resultadoErroneo() si no pudo.

El archivo index.php debería quedar así:

<!DOCTYPE html>
<html>
 <head> 
    <!-- Importación de la librería de jquery. -->
    <script type="text/javascript" src="https://code.jquery.com/jquery-1.8.2.min.js"></script>
    <script type="text/javascript"> 
       function cargando(){
          $("#respuesta").html('Cargando');
       } 
       function resultadoOk(){
          $("#respuesta").html('El archivo ha sido subido exitosamente.');
       } 
       function resultadoErroneo(){
          $("#respuesta").html('Ha surgido un error y no se ha podido subir el archivo.');
       } 
    $(document).ready(function(){
       $("#boton_subir_archivo").click(function(){
          cargando();
       });
    }); 
 </script>
 </head>
 <body> 
    <form action="subir_archivo.php" class="formularios" method="post" enctype="multipart/form-data" target="contenedor_subir_archivo">
       <label> Archivo </label>
       <input type="file" name="archivo" />
       <input type="submit" id="boton_subir_archivo" />
       <div id="respuesta"></div>
       <iframe width="1" height="1" frameborder="0" name="contenedor_subir_archivo" style="display: none"></iframe>
    </form> 
 </body>
</html>

Bueno ahora veremos el controlador que procesará el archivo subido, copien esto en su archivo subir_archivo.php:

<?php 
 //Verificamos si existe un archivo a subir.
 if(isset($_FILES['archivo'])){ 
    //Si el archivo puede ser subido igualará la variable $arhivo_subido a true, sino a false.
    if(move_uploaded_file($_FILES['archivo']['tmp_name'], 'archivos/' . $_FILES['archivo']['name'])){
       $arhivo_subido = true;
    }else{
       $arhivo_subido = false;
    } 
?> 
 <!DOCTYPE html>
 <html>
 <head>
 </head>
 <body>
    <!-- Al cargar la página, según el valor de la variable que indica si el archivo se subió entonces mostrará el mensaje correspondiente, llamando a una función del padre. -->
    <?php if($arhivo_subido): ?>
       <script type="text/javascript">
          parent.resultadoOk();
       </script>
    <?php else: ?>
       <script type="text/javascript">
          parent.resultadoErroneo();
       </script>
    <?php endif; ?>
 </body>
 </html>
<?php 
 } 
?>

Bueno, este controlador será el que el mueva el archivo a la carpeta archivos, y dependiendo de si los subió o no devolverá un script de javascript indicando si el archivo ha sido subido o no. Sin embargo, si alcanzaste a leer este último código habrás notado algo, las llamadas a las funciones adelante tienen una palabra llamada parent seguida por un punto.

Por si no sabés de qué se trata, parent es un objeto de javascript que permite llamar a funciones y objetos de páginas padres. Osea, nosotros tenemos una página index.php que tiene tres funciones y un iframe, dentro de ese iframe se carga la página subir_archivo.php, por tanto subir_archivo.php pasaría a ser una página hija de index.php, y para llamar a funciones padres, se lo debe hacer mediante el objeto parent.

Bueno, espero que lo haya hecho fácil, cualquier cosa, por acá me preguntan.

Saludos a todos.

Anterior: Ajax fácil, segunda parte


2 Respuestas a “Ajax fácil, tercera parte (Subir archivos al servidor)”

  1. Hola, tu explicacion es excelente y me funciona a la perfeccion.

    Quisiera saber si esto es posible para subir varios (3) archivos al mismo tiempo.

    Pero solamente se queda hasta «Cargando»

    Y de alli no avanza.
    Alguna idea???

    Muchas gracias de antemano.

  2. Existirá manera de poder sacar el archivo index a una carpeta fuera del servidor? Hice las pruebas y se queda en cargando la imagen, o alguna solución para que esto suceda?