Cómo subir archivos con CodeIgniter y AJAX

Cargar archivos de forma asíncrona puede ser una molestia en el mejor de los casos, pero cuando se combina con CodeIgniter, puede ser una experiencia particularmente frustrante. Finalmente encontré una manera que no solo funciona de manera consistente, sino que sigue el patrón MVC. Sigue leyendo para descubrir cómo!

Por cierto, puedes encontrar algunos complementos y códigos de código útiles CodeIgniter en Envato Market, así que consulta lo que puedes encontrar para tu próximo proyecto..


Prefacio

En este tutorial, usaremos el framework de PHP CodeIgniter, el framework de JavaScript jQuery y el script AjaxFileUpload.

Se asume que tiene un conocimiento práctico de CodeIgniter y jQuery, pero no es necesario ningún conocimiento previo de AjaxFileUpload. También se supone que ya tiene una instalación de CodeIgniter ya configurada.

En aras de la brevedad, se ha omitido la carga de ciertas bibliotecas / modelos / ayudantes. Estos se pueden encontrar en el código fuente suministrado, y son cosas bastante estándar.

También necesitarás una base de datos, y una tabla, llamada archivos. El SQL para crear dicha tabla es:

CREAR TABLA 'archivos' ('id' int NOT NULL AUTO_INCREMENT PRIMARY KEY, 'nombre de archivo' varchar (255) NOT NULL, 'título' varchar (100) NOT NULL);

Al final del tutorial, la estructura de su archivo debería verse similar a esto (omitiendo carpetas / archivos no registrados):

public_html /
-- solicitud/
---- controladores /
------ subir.php
---- modelos /
------ archivos_modelo.php
---- puntos de vista/
------ subir.php
------ archivos.php
-- css /
---- style.css
-- archivos /
-- js /
---- AjaxFileUpload.js
---- site.js


Paso 1 - Creando el formulario

Configurar el controlador

Primero, necesitamos crear nuestro formulario de carga. Crear un nuevo controlador, llamado subir, y en el método de índice, renderizar la vista. subir.

Su controlador debe tener este aspecto:

la carga de clase amplía CI_Controller función pública __construct () parent :: __ construct (); $ this-> load-> model ('files_model'); $ this-> load-> database (); $ this-> load-> helper ('url');  índice de función pública () $ this-> load-> view ('upload'); 

También estamos cargando en el modelo de archivos, por lo que podemos utilizarlo en nuestros métodos. Una mejor alternativa puede ser cargarlo automáticamente en su proyecto real.

Crear el formulario

Crea tu vista, subir.php. Esta vista contendrá nuestro formulario de subida..

         

Subir archivo

Archivos

No te olvides de colocar ajaxfileupload.js en js /.

Como puede ver, estamos cargando nuestros scripts en la parte superior; jQuery, AjaxFileUpload y nuestro propio archivo js. Esto albergará nuestro JavaScript personalizado.

Entonces, simplemente estamos creando un formulario HTML estándar. El archivo #files div vacío es donde estará nuestra lista de archivos cargados.

Algunos CSS simples

Solo para que no se vea bastante tan malo, vamos a agregar algunos CSS básicos a nuestro archivo style.css en css /.

h1, h2 font-family: Arial, sans-serif; tamaño de fuente: 25px;  h2 font-size: 20px;  label font-family: Verdana, sans-serif; tamaño de fuente: 12px; bloqueo de pantalla;  entrada relleno: 3px 5px; ancho: 250px; margen: 0 0 10px;  input [type = "file"] padding-left: 0;  entrada [type = "submit"] width: auto;  #files font-family: Verdana, sans-serif; tamaño de fuente: 11px;  #files strong font-size: 13px;  #files a float: right; margen: 0 0 5px 10px;  #files ul estilo de lista: ninguno; relleno-izquierda: 0;  #files li width: 280px; tamaño de fuente: 12px; relleno: 5px 0; borde inferior: 1px sólido #CCC; 

Paso 2 - El Javascript

Crear y abrir site.js en js /. Coloque el siguiente código:

$ (function () $ ('# upload_file'). submit (function (e) e.preventDefault (); $ .ajaxFileUpload (url: './ upload / upload_file /', secureuri: false, fileElementId: ' userfile ', dataType:' json ', data: ' title ': $ (' # title '). val (), success: function (data, status) if (data.status! =' error ')  $ ('# archivos'). html ('

Recargar archivos?

'); refresh_files (); $ ('# title'). val ("); alert (data.msg);); devolver falso;););

El JavaScript secuestra el formulario enviar y AjaxFileUpload toma el control. En el fondo, crea un iframe y envía los datos a través de ese.

Estamos pasando el valor del título en el parámetro de datos de la llamada AJAX. Si tuviera más campos en el formulario, los pasaría aquí.

Luego verificamos nuestra devolución (que estará en JSON). Si no se produjo ningún error, actualizamos la lista de archivos (ver más abajo), borramos el campo del título. En cualquier caso, alertamos el mensaje de respuesta..


Paso 3 - Subiendo el archivo

El controlador

Ahora a subir el archivo. La URL a la que estamos subiendo es / upload / upload_file /, así que cree un nuevo método en el subir controlador, y coloque el siguiente código en él.

función pública upload_file () $ status = ""; $ msg = ""; $ file_element_name = 'userfile'; if (vacío ($ _ POST ['title'])) $ status = "error"; $ msg = "Por favor ingrese un título";  if ($ status! = "error") $ config ['upload_path'] = './files/'; $ config ['allowed_types'] = 'gif | jpg | png | doc | txt'; $ config ['max_size'] = 1024 * 8; $ config ['encrypt_name'] = TRUE; $ this-> load-> library ('upload', $ config); if (! $ this-> upload-> do_upload ($ file_element_name)) $ status = 'error'; $ msg = $ this-> upload-> display_errors (",");  else $ data = $ this-> upload-> data (); $ file_id = $ this-> files_model-> insert_file ($ data ['file_name'], $ _POST ['title']); if ($ file_id) $ status = "success"; $ msg = "Archivo cargado exitosamente";  else unlink ($ data ['full_path']); $ status = "error"; $ msg = "Algo salió mal al guardar el archivo, inténtelo de nuevo.";  @unlink ($ _ FILES [$ file_element_name]);  echo json_encode (array ('status' => $ status, 'msg' => $ msg)); 

Este código se carga en la biblioteca de carga de CodeIgniter con una configuración personalizada. Para una referencia completa de él, echa un vistazo a los documentos CodeIgniter.

Hacemos una verificación simple para determinar si el título está vacío o no. Si no es así, cargamos en la biblioteca de carga de CodeIgniter. Esta biblioteca maneja gran parte de nuestra validación de archivos para nosotros.

A continuación, intentamos subir el archivo. si tiene éxito, guardamos el título y el nombre del archivo (se pasa a través de la matriz de datos devueltos).

Recuerde eliminar el archivo temporal del servidor y hacer eco del JSON para que sepamos lo que sucedió..

El modelo

De acuerdo con el patrón MVC, nuestra interacción DB será manejada por un modelo.

Crear archivos_modelo.php, y añada el siguiente código:

la clase Files_Model extiende CI_Model public function insert_file ($ filename, $ title) $ data = array ('filename' => $ filename, 'title' => $ title); $ this-> db-> insert ('files', $ data); devuelve $ this-> db-> insert_id (); 

Carpeta de archivos

También deberíamos crear la carpeta donde se subirán nuestros archivos. Crea un nuevo archivo en tu raíz web llamado archivos, asegurándose de que sea escribible por el servidor.


Paso 4 - La lista de archivos

Tras una carga exitosa, necesitamos actualizar la lista de archivos para mostrar el cambio.

El JavaScript

Abierto site.js y agregue el siguiente código al final del archivo, debajo de todo lo demás.

función refresh_files () $ .get ('./ upload / files /') .success (function (data) $ ('# files'). html (data);); 

Esto simplemente llama a una url e inserta los datos devueltos en un div con un id de archivos.

Necesitamos llamar a esta función en la carga de la página para mostrar inicialmente la lista de archivos. Agregue esto en la función de documento listo en la parte superior del archivo:

refresh_files ();

El controlador

La URL a la que llamamos para obtener la lista de archivos es / upload / files /, así que cree un nuevo método llamado archivos, y colocar en el siguiente código:

archivos de funciones públicas () $ files = $ this-> files_model-> get_files (); $ this-> load-> view ('files', array ('files' => $ files)); 

Un método bastante pequeño, usamos nuestro modelo para cargar los archivos guardados actualmente y pasarlo a una vista.

El modelo

Nuestro modelo se encarga de la recuperación de la lista de archivos. Abrir archivos_modelo.php, y añadir en el get_files () función.

función pública get_files () return $ this-> db-> select () -> from ('files') -> get () -> result (); 

Bastante simple: selecciona todos los archivos almacenados en la base de datos.

La vista

Necesitamos crear una vista para mostrar la lista de archivos. Crea un nuevo archivo, llamado archivos.php, y pega en el siguiente código:

 
  • id?> "> Eliminar título?>
    nombre de archivo?>

No hay archivos subidos

Esto recorre los archivos y muestra el título y el nombre de archivo de cada uno. También mostramos un enlace de eliminación, que incluye un atributo de datos del ID de archivo.


Borrando el archivo

Para redondear el tutorial, agregaremos la funcionalidad para eliminar el archivo, también utilizando AJAX..

El JavaScript

Agregue lo siguiente en la función de documento listo:

$ ('. delete_file_link'). live ('click', function (e) e.preventDefault (); if (confirme ('¿Está seguro de que desea eliminar este archivo?')) var link = $ (esto ); $ .ajax (url: './upload/delete_file/' + link.data ('file_id'), dataType: 'json', success: function (data) files = $ (# files); if ( data.status === "success") link.parents ('li'). fadeOut ('fast', function () $ (this) .remove (); if (files.find ('li'). longitud == 0) files.html ('

No hay archivos subidos

'); ); else alert (data.msg); ); );

Siempre es una buena idea obtener una confirmación del usuario al eliminar información.

Cuando se hace clic en un enlace de eliminación, mostramos un cuadro de confirmación que pregunta si el usuario está seguro. Si lo son, hacemos una llamada a / upload / delete_file, Y si tenemos éxito, lo eliminamos de la lista..

El controlador

Como arriba, el url que estamos llamando es / upload / delete_file /, entonces crea el método borrar archivo, y añada el siguiente código:

función pública delete_file ($ file_id) if ($ this-> files_model-> delete_file ($ file_id)) $ status = 'success'; $ msg = 'Archivo eliminado con éxito';  else $ status = 'error'; $ msg = 'Algo salió mal al eliminar el archivo, inténtelo de nuevo';  echo json_encode (array ('status' => $ status, 'msg' => $ msg)); 

Una vez más, dejamos que el modelo haga el trabajo pesado, haciendo eco de la salida.

El modelo

Ahora estamos en la última pieza del rompecabezas: nuestros dos últimos métodos.

función pública delete_file ($ file_id) $ file = $ this-> get_file ($ file_id); if (! $ this-> db-> where ('id', $ file_id) -> delete ('files')) return FALSE;  unlink ('./ files /'. $ file-> filename); volver VERDADERO  función pública get_file ($ file_id) return $ this-> db-> select () -> from ('files') -> where ('id', $ file_id) -> get () -> row (); 

Debido a que solo pasamos la ID, necesitamos obtener el nombre del archivo, por lo que creamos un nuevo método para cargar el archivo. Una vez cargado, eliminamos el registro y eliminamos el archivo del servidor..

Eso es todo, tutorial completo! Si lo ejecuta, debería poder cargar un archivo, verlo aparecer y luego eliminarlo; todo sin salir de la pagina.


Pensamientos finales

Obviamente, las vistas pueden ser más bonitas, pero este tutorial debería haberle dado lo suficiente para poder integrar esto en su sitio..

Sin embargo, hay algunas deficiencias en este método:

  • Solo puede cargar un archivo a la vez, pero esto se puede corregir fácilmente mediante el uso de un servicio como Uploadify.
  • No hay barra de progreso incorporada en el script.
  • Podríamos reducir las llamadas SQL actualizando los archivos. div al subir el archivo, en lugar de reemplazarlos completamente.

Gracias por leer!