Recientemente me han pedido que añada en una de las webs que administro un enlace (de manera artesanal) para poder descargar un documento concreto.
Bien… la mayoría pensaréis que es algo trivial, porque seguramente uso alguno de los múltiples cms que existen en el mercado (y no os equivocáis), que seguro implementa de core o mediante algún sencillo plugin… Y es totalmente cierto. Pero, como os planteaba en la primera línea, me lo han pedido de forma “artesanal”.
En fin, no le demos mas vueltas, porque no tiene mucho sentido.
Sin más preámbulos, os dejo un código escrito en php que hará las delicias de los mas necesitados.
<?php
// accepted file extensions
$extensions = array("pdf","mp3","zip","rar");
// file name to download
$file = $_GET["file"];
// file size
$size = filesize($file);
// Prevent go throught directories
if(strpos($file,"/")!==false){
die("Permission denied to change directory, please, especify only a file name");
}
// test the file estension
$ftmp = explode(".",$file);
$fExt = strtolower($ftmp[count($ftmp)-1]);
if(!in_array($fExt,$extensions)){
die("ERROR: File extension not recognized: $fExt");
}
// if it was ok, let's download it
header("Content-Transfer-Encoding: binary");
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=$file");
header("Content-Length: $size");
$fp=fopen("$file", "r");
fpassthru($fp);
?>
Expliquemos un poco las líneas mas importantes
- 3 : definimos un array de extensiones de fichero aceptadas (en este caso, pdf, mp3, zip, rar…)
- 6 : obtenemos de la request (query string) el nombre del fichero a descargar, mediante el parámetro file
- 9 : validamos el parámetro, y no permitimos que se especifiquen nombres de fichero que contengan cambios de directorio, para prevenir descargas no deseadas (si encontramos una / terminamos con un error)
- 14 : extraemos la extensión del fichero solicitado
- 15 : eliminamos el . de la extensión y lo convertimos a minúsculas, para asemejarlo al array de aceptados
- 16 : comprobamos que la extensión existe en el array de extensiones aceptadas, y en caso contrario, finalizamos con un mensaje de error adecuado
- 21 : modificamos la cabecera de respuesta html para indicar que contiene un binario
- 22 : añadimos a la cabecera html el nombre del fichero a descargar
- 23 : abrimos el fichero como lectura (aquí es donde podemos comprobar que el fichero debe estar en la ruta actual en la que se encuentra esta misma página php, aunque si deseais cambiar el directorio de almacenamiento de los ficheros, es tan fácil como añadir la ruta delante del $file
- 24 : se escribe el fichero en la response de la página
Como véis, el procedimiento es muy sencillo:
- Subid vuestro fichero al directorio desde dónde descargaréis los ficheros
- Subid vuestro código al directorio desde dónde descargaréis los ficheros (este es el caso sencillo, pero como os he explicado sobre la línea 23, la ruta podría variarse sin problemas)
- Añadid un link a vuestra imagen o texto de descarga, (supongamos que yo tengo el tinglado montado en /files) del tipo: /files/download.php?file=nombre_fichero
Y ya lo tenéis.
Fácil, ¿verdad?
Espero haberos sido de ayuda!
Jordi




