martes, 11 de agosto de 2009

Usando Media View para descargar archivos

Estoy trabajando en un plugin para gestionar archivos subidos a una aplicación web y entre otras cosas he aprendido a utilizar las Media Views para facilitar las descargas de esos mismos archivos, estén almacenados donde estén.

La documentación base que he utilizado es la página del manual y un post del siempre recomendable blog sobre CakePHP de Teknoid. A partir de aquí, y tras unas pocas pruebas parece que he conseguido dominar este tipo de vistas.

Qué es una Media View

Se trata de un tipo de vista especial para enviar archivos binarios al usuario. Se utiliza en lugar de las vistas por defecto y la verdad es que se encarga de casi todo ella solita.

Hay dos ventajas principales en usar MediaView en lugar de enlaces directos al archivo:

  • Podemos enviar archivos que no estén bajo el webroot, evitando así que los usuarios puedan descargarlos reconstruyendo la URL, algo relativamente fácil conociendo cómo funciona CakePHP
  • Al realizar la descarga a través de una acción de un controlador, ésta puede tener el acceso controlado a través de Auth o el método que tengamos, con lo cual, incluso con la URL sólo los usuarios autorizados podrían descargar el archivo.
Empleando Media View

Para poder empezar a utilizarlas debemos especificarlo en la acción apropiada del controlador, con la siguiente línea:

$this->view = 'Media';

A continuación hay que pasarle varios parámetros para identificar el archivo, una forma sencilla sería así:

$params = array(
'id' => 'nombre_del_archivo.ext',
'name' => 'Nombre Humano del Archivo',
'download' => true,
'extension' => 'ext',
'mimeType' => array('ext' => 'mimeType/subtype'),
'path' => 'path/a/la/carpeta/del/archivo/',
);
$this->set($params);

Trataré de explicarme:

Empiezo por el final. A la vista habría que pasarle los parámetros id, name, etc. Pasando un array con las claves necesarias hacemos lo mismo. A mí al principio me extrañó esta manera de hacerlo (lo típico es pasar $this->set('params', $params);) pero al ver el código de media.php, me quedó claro que CakePHP desempaqueta el array. En consecuencia, puedes ponerle al array el nombre que quieras, no hace falta que sea $params mientras que las claves sean correctas.

Ahora voy por los parámetros o claves del array.

id: Es el nombre del archivo que vamos a enviar, tal cual está en el sistema de archivos.

name: Es el nombre con el que queremos que el usuario guarde el archivo en su disco duro, esto nos permite ponerle un nombre humanizado si preferimos.

extension: Se explica solo, es la extensión del archivo

download: si está en true, fuerza la descarga el archivo

mimeType: esta parte tiene truco. A mí me costó un poquito cogerle el punto. La clase MediaView "reconoce" una buena cantidad de tipos mime que podrían tener los archivos, pero no todos. El problema es que no se descargan si no proporcionamos el mimeType correcto. Afortunadamente, en esta clave podemos declarar uno o más mimeType aceptables para cada archivo concreto. La forma de declararlos es poner la extensión como clave y como valor el tipo mime. En mi caso, al subir el archivo tomo nota del mimeType y no tengo más que recuperarlo en la acción de descarga y pasarlo en esta clave. De este modo me ha permitido descargar diversos tipos de archivos que MediaView no admitía (como los .rar).

path: es la ruta al archivo relativa a la carpeta de la aplicación (concretamente utiliza el valor de la constante APP), por lo cual, podemos descargar archivos que no estén bajo el webroot, sino en un nivel superior y fuera de él. Esto es ideal si no queremos que los usuarios puedan descargar archivos "imaginándose" la URL. Debe llevar el separador de directorios al final. Recuerda construir los paths usando la constante DS si necesitas que la aplicación sea portable.

size: se puede especificar la clave size para indicar el tamaño de archivo, pero yo no he conseguido que los archivos se descargasen. No sé dónde esta el error.

Y ya está.

No hay comentarios: