Por circunstancias de la vida, me interesa descagar ficheros, concretamente en formato PDF, desde un servidor web. Normalmente esto se hace con un simple
a href
, pero en este caso me interesa que la petición "pase" por CF para controlar que tan sólo usuarios autorizados puedan descargarlos, razón por la cual, además, dichos ficheros están en un directorio fuera de la raíz del servidor, y por tanto, no son accesibles via
a href
.
En ColdFusion la solución para esto se llama
cfcontent
, una etiqueta que permite indicar al navegador el tipo MIME del contenido que le vamos a entregar, y además, permite señalar un fichero que será el contenido a descargar.
Así que, en teoría, un simple
<cfcontent type="application/pdf" file="rutaabsolutadelfichero.pdf">
debería servir. Pues no. Bueno, casi. Hay dos problemas:
* Internet Explorer no acaba de captar lo del MIME-Type, y muestra el contenido del fichero como un fichero de texto. Queda mono, pero no es eso...
* otros navegadores lo interpretan correctamente, pero muestran el contenido del fichero en el navegador. Me interesa más que lo descargue, o al menos, que le pregunte al usuario si lo que quiere descargar.
La solución a ambos problemas es otra etiqueta,
cfheader
, que se usa para enviar "a mano" cabeceras HTTP al navegador, antes de entregarle el contenido de la página. En este caso, una cabecera
content-disposition
, que le indica al navegador como debe presentar el contenido que le ofrecemos:
inline
para mostrarlo en el navegador, o
attachment
para descargarlo. En este último caso, todo navegador bien educado le preguntará al usuario que desea hacer, si descargar el fichero, o abrirlo directamente.
En resumen, lo correcto para lo que quería hacer es:
<cfheader name = "content-disposition" value = "attachment; filename=nombredelfichero.pdf">
<cfcontent type = "application/pdf" file = "rutaabsolutadelfichero.pdf">
Esto funciona perfectamente tanto para Explorer como para otros navegadores, siempre que el nombre del fichero sea normalito, es decir, sin espacios, eñes, tildes, ni nada por el estilo. Que, por otro lado, es la forma recomendable en que debería ir todo nombre de fichero si queremos que sea lo más transportable posible. Si por causas de fuerza mayor no podemos estar seguros de ello, el siguiente código es más adecuado (formatea el nombre de fichero -hasta el punto que separa la extensión- como si fuera una URL, lo que evita bastantes problemas):
<cfset sExtension = ListLast(nombrecompletofichero, ".")>
<cfset sNombreFichero = ListDeleteAt(nombrecompletofichero, ListLen(nombrecompletofichero, "."), ".")>
<cfheader name="content-disposition" value="attachment; filename=#urlencodedformat(sNombreFichero)#.#sExtension#">
<cfcontent type="application/pdf" file="rutaabsolutadelfichero.pdf">