Cargar imágenes al servidor web con CodeIgniter, CSS, Ajax y JQuery
Tiempo total: 5 días con 15:42:7 hrs
En algunas ocasiones he necesitado utilizar el mismo código en distintas aplicaciones para poder cargar una imagen, pdf o csv al servidor web utilizando Ajax con JQuery mostrando el porcentaje de carga. En esta publicación observaras el código necesario para hacer esto.
Cabecera
Para hacer funcionar el código, es necesario utilizar Jquery y archivos JS y CSS externos:
<link href="<?=URL?>/css/css.css" rel="stylesheet"> <script type="text/javascript" src="<?=URL?>js/jquery.min.js"></script> <script type="text/javascript"> var URL = "<?=URL?>"; </script> <script type="text/javascript" src="<?=URL?>js/js.js"></script>
Si utilizamos CodeIgniter es necesario definir la variable global URL en application/config/constants.php, de la misma manera la definimos en Javscript.
Código HTML
Si la carga se hace al instante entonces no es necesario que el input “file” este dentro del formulario HTML, podemos utilizar un input “hidden” que estará dentro del mismo.
<b>Archivo SCV:</b> <div class="file image_bar floatleft"> <div class="file container"> </div> <div class="file bar">0%</div> </div> <input type="file" name="form_upload_csv" id="form_upload_csv"> <?php echo form_open(URL.'controlador/guardar'); ?> <input type="hidden" name="archivo_csv" id="archivo_csv" value="" /> <?php echo form_submit('submit','Guardar', "id='submit' disabled"); ?> <?php echo form_close(); ?>
En este ejemplo se cargará un archivo CSV, se observa que el botón para guardar esta deshabilitado (no puede estar habilitado si no se ha subido el archivo al servidor).
Diseño CSV
El formulario debe de observarse de la siguiente manera:
El código CSV es el siguiente:
.content .image_bar{ position: relative; width: 100%; margin-top: 5px; z-index: 10; margin-bottom: 10px; } .content .image_bar .container{ position: absolute; width: 100%; height: 20px; background-color: #f0ad4e; border: 1px solid #a97b39; z-index: 1; /* all */ border-top-left-radius: 2px; border-top-right-radius: 2px; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; /* firefox */ -moz-border-radius-topleft: 2px; -moz-border-radius-topright: 2px; -moz-border-radius-bottomleft: 2px; -moz-border-radius-bottomright: 2px; /* webkit */ -webkit-border-top-left-radius: 2px; -webkit-border-top-right-radius: 2px; -webkit-border-bottom-left-radius: 2px; -webkit-border-bottom-right-radius: 2px; /**/ } .content .image_bar .bar{ position: relative; width: 0%; height: 18px; top: 2px; left: 1px; background-color: #15a060; z-index: 2; text-align: center; /* all */ border-top-left-radius: 2px; border-top-right-radius: 2px; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; /* firefox */ -moz-border-radius-topleft: 2px; -moz-border-radius-topright: 2px; -moz-border-radius-bottomleft: 2px; -moz-border-radius-bottomright: 2px; /* webkit */ -webkit-border-top-left-radius: 2px; -webkit-border-top-right-radius: 2px; -webkit-border-bottom-left-radius: 2px; -webkit-border-bottom-right-radius: 2px; /**/ }
En las clases CSS en el código HTML se puede observar “file”, la cual es una clase general que me ayuda a establecer los parámetros necesarios que cada div debe de tener, esto para logar obtener compatibilidad con navegadores (créeme al decirte que no existen “trucos” CSS para poder obtener la compatibilidad).
.file{ position: relative; width: 100%; height: auto; top: 0px; left: 0px; }
Carga con Ajax/Jquery
La función que servirá para enviar el archivo CSV al servidor es la siguiente:
function guardar(){ $("#form_upload_csv").change(function() { $.each($(this).prop("files"), function(key,value){ var filename = value['name']; var ext = filename.split('.').pop(); formData= new FormData(); formData.append("image", value); if(ext == "csv"){ $.ajax({ url: URL+"controlador/cargar_csv", type: "POST", data: formData, xhr: function() { // custom xhr myXhr = $.ajaxSettings.xhr(); if(myXhr.upload){ // check if upload property exists myXhr.upload.addEventListener('progress',function(evt){ OnProgress(evt); }, false); // for handling the progress of the upload } return myXhr; }, processData: false, contentType: false, success: function(data){ data = data.split("_DONE_"); data = data[1]; if(data=="OK"){ $('#archivo_csv').val(filename); $('#submit').removeAttr('disabled'); }else{ FailProgress(); } } }); }else{ FailProgress(); } }); }); }
En la segunda línea observamos la instrucción “$.each($(this).prop(“files”), function(key,value){“ la cual permite utilizar el código para hacer una carga de varios archivos (únicamente debemos de implementar el código y recordar definir las variables dentro de ese mismo bucle para que cada una almacene las variables creadas en sí mismo).
Para no enviar archivos PDF, imágenes o documentos de Word, utilizamos de primero la validación javascript para no enviar archivos con otras extensiones.
Las dos funciones utilizadas en el código son las siguientes:
function OnProgress(evt){ var percentComplete = evt.loaded / evt.total; $('.image_bar .bar').css({'width':(parseInt(percentComplete * 100)+'%')}); $('.image_bar .bar').text(parseInt(percentComplete * 100)+'%'); } function FailProgress(){ $('.content .image_bar .bar').css({'width':'0%'}); $('.content .image_bar .bar').text('0%'); $("#form_upload_csv").val(""); alert('Por favor inténtalo de nuevo.'); }
Y para poder activar el código de la función guardar(), debemos de llamarla al cargar la página:
$(document).ready(function () { try{guardar();}catch(err){} });
Código Php
Es bastante simple, de nuevo se hace la validación para no cargar archivos con distintas extensiones (si quieres más seguridad debes de obtener más información del contenido del archivo para validar que sea CSV).
public function cargar_csv(){ $files = array(); foreach($_FILES as $file) { $urlImagen='csv/' . $file['name']; $ext = pathinfo($urlImagen, PATHINFO_EXTENSION); if(strtolower($ext)=="csv" && move_uploaded_file($file['tmp_name'], $urlImagen)){ echo "1_DONE_OK_DONE_1"; }else echo "1_DONE_FAIL_DONE_1"; } }