Visitas: 255  
Tiempo total: 4 días con 2:56:40 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:

formulario

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";
}
}