Subir archivos con CakePHP y jQuery

En este turorial veremos como se puede implementar la carga de archivos utilizando CakePHP y jQuery.

1. CakePHP. Carga de archivos
Utilizando los consejos publicados en este post, implementaremos la lógica PHP para subir archivos al servidor. El siguiente método toma el nombre del directorio en el servidor al cual se quieren subir los archivos, el array de archivos del formulario y un identificador opcional en caso que se desee crear un subdirectorio en donde guardar el archivo.

/**
* uploads files to the server
* @params:
*		$folder 	= the folder to upload the files e.g. 'img/files'
*		$formdata 	= the array containing the form files
*		$itemId 	= id of the item (optional) will create a new sub folder
* @return:
*		will return an array with the success of each file upload
*/
function uploadFiles($folder, $formdata, $itemId = null) {
// setup dir names absolute and relative
$folder_url = WWW_ROOT.$folder;
$rel_url = $folder;

// create the folder if it does not exist
if(!is_dir($folder_url)) {
mkdir($folder_url);
}

// if itemId is set create an item folder
if($itemId) {
// set new absolute folder
$folder_url = WWW_ROOT.$folder.'/'.$itemId;
// set new relative folder
$rel_url = $folder.'/'.$itemId;
// create directory
if(!is_dir($folder_url)) {
mkdir($folder_url);
}
}

// list of permitted file types, this is only images but documents can be added
$permitted = array('image/gif','image/jpeg','image/pjpeg','image/png');

// loop through and deal with the files
foreach($formdata as $file) {
// replace spaces with underscores
$filename = str_replace(' ', '_', $file['name']);
// assume filetype is false
$typeOK = false;
// check filetype is ok
foreach($permitted as $type) {
if($type == $file['type']) {
$typeOK = true;
break;
}
}

// if file type ok upload the file
if($typeOK) {
// switch based on error code
switch($file['error']) {
case 0:
// check filename already exists
if(!file_exists($folder_url.'/'.$filename)) {
// create full filename
$full_url = $folder_url.'/'.$filename;
$url = $rel_url.'/'.$filename;
// upload the file
$success = move_uploaded_file($file['tmp_name'], $url);
} else {
// create unique filename and upload file
ini_set('date.timezone', 'Europe/London');
$now = date('Y-m-d-His');
$full_url = $folder_url.'/'.$now.$filename;
$url = $rel_url.'/'.$now.$filename;
$success = move_uploaded_file($file['tmp_name'], $url);
}
// if upload was successful
if($success) {
// save the url of the file
$result['urls'][] = $url;
} else {
$result['errors'][] = "Error uploaded $filename. Please try again.";
}
break;
case 3:
// an error occured
$result['errors'][] = "Error uploading $filename. Please try again.";
break;
default:
// an error occured
$result['errors'][] = "System error uploading $filename. Contact webmaster.";
break;
}
} elseif($file['error'] == 4) {
// no file was selected for upload
$result['nofiles'][] = "No file Selected";
} else {
// unacceptable file type
$result['errors'][] = "$filename cannot be uploaded. Acceptable file types: gif, jpg, png.";
}
}
return $result;
}

Dado que lo voy a usar en varios controllers, lo agregué al AppController. Un ejemplo de cómo usarlo sería el siguiente:

En la vista: <?php echo $form->file(‘File.image’); ?>
En el controller:


$fileOK = $this->uploadFiles('files', $this->data['File']);
// si el archivo fue subido correctamente
if(array_key_exists('urls', $fileOK)) {
// guardar la url en la informacion del from
$this->data['Post']['image_url'] = $fileOK['urls'][0];
}

2. jQuery

Para el frontend, usamos el plugin AjaxUpload de jQuery, disponible aquí. Les recomiendo que vean los ejemplos disponibles desde esa misma página. Una vez descargado, (requerden que también necesitan jQuery), lo guardamos en la carpeta app/webroot/js. Para poder utilizarlo, no olviden incluirlo en la vista: <?php $this->addScript($javascript->link(‘ajaxupload’)); ?>

Un ejemplo de código javascript para inicializar AjaxUpload es el siguiente:

$(document).ready(function(){
 new AjaxUpload('#att_file', {
  action: 'controller/action',
  name: 'data[Attachment][path]',
  autoSubmit: true,
  onComplete : function(file, response){
    alert('Carga Filanizada');
  },
  onChange: function(){
  }
 });
});//document ready

Debemos setear el action para que apuente al controllador y acción correspondiente.

AjaxUpload permite utilizar cualquier elemento como botón para abrir el cuadro de dialogo de seleccionar archivos. Por ejemplo, podríamos usar un div:

<div id='att_file'>Cargar Archivos</div>

AjaxUpload utiliza un iframe oculto para cargar el archivo, por lo que no es una técnica AJAX propiamente dicha, aunque logra una experiencia de uso similar.

Podríamos utlizar los eventos onChange y onComplete para mostrar un mensaje de Loading. Si es necesario adjuntar más datos para ser enviados por el formulario, se puede utilizar la propiedad data.

Con esto tenemos todos los elementos necesarios para tener carga de archivos AJAX utilizando CakePHP.

Share and Enjoy:
  • Digg
  • del.icio.us
  • StumbleUpon
  • Technorati
  • Facebook

3 Comentarios to “Subir archivos con CakePHP y jQuery”

  1. perfecto eso era algo que estaba pensando y estuve buscando usar un framework como Jquery por que el framework predeterminado segun lo que he leido es Prototype.
    pero este articulo me aclara que tambien podemos usar Jquery. muy agredecido al autor de este articulo por este aporte tan bueno.

  2. Sergio, jQuery es muchisimo más cómodo y sencillo de aprender que Prototype, por lo que yo lo recomendaría antes q Prototype

  3. Muy buen turorial. Pero tengo unas dudas y la verdad no se que estoy haciendo mal. A mi me muestra el mensaje de que subio el archivo, peor reviso y no lo sube.

    No se si podria colocar un ejemplo mas completo.

Deja un comentario