Spiga

  PHP

Forzar descargas con PHP

12 de Febrero de 2008 por nicoh

Introducción

Muchas veces navegando, nos encotnramos con sitios web que contienen enlaces hacia archivos como ser MP3, JPG, PDF, etc.

Cuando hacemos click en estos enlaces, por lo general se abren directamente, o sea, los MP3 en nuestro reproductor de audio, los PDF en el Acrobat Reader (o dentro del navegador), los JPG en el visor de imágenes, etc.

Lo que sucede, es que puede que nosotros queramos que el archivo no se abra automaticamente, sino que aparezca la típica ventana de descarga.

Código

Para lograr el resultado deseado, debemos crear un archivo llamado descargar.php (o como queramos) y ubicarlo en el directorio del hosting donde se encuentran nuestros archivos.

PHP:
  1. <br />
  2. <?php<br />
  3.     //  descargar.php<br />
  4.     $f = $_GET["f"];<br />
  5.     header("Content-type: application/octet-stream");<br />
  6.     header("Content-Disposition: attachment; filename=$f");<br />
  7.     $fp=fopen("$f", "r");<br />
  8.     fpassthru($fp);<br />
  9. ?><br />

Implementación

El modo de uso es realmente sencillo, solo debemos modificar el destino de nuestro enlace de archivo.jpg a descargar.php?f=archivo.jpg.

Quedando en enlace de la siguiente manera:

HTML:
  1. <br />
  2. <a href="descargar.php=?archivo.jpg">Descargar Imagen</a><br />

La verdad es que es un método muy facil de implementar y que nos brinda una solución frente a este problema.

A mi gusto debería implementarse en los sitios web con enlaces hacia archivos PDF, ya que generalmente cuando abrimos uno o varios de estos, el navegador comienza a ponerse muy lento.

Fuente | DaveMM

ACTUALIZACIÓN

Corey me informa que corrigió un bug de seguridad en su código que permitía la descarga de cualquier tipo de archivos por medio del script, como archivos PHP por ejemplo.
Para corregirlo, usamos el código actualizado:

PHP:
  1. <?php
  2.     $f = $_GET["f"];
  3.     $archivos = array('.mp3','.jpg','.pdf');
  4.     $extension = strtolower(strstr($f,'.'));
  5.     if(strpos($f,'/')!==false)
  6.         exit("Los archivos de otros <b>directorios</b> no son descargables.");</p>
  7.     if(!in_array($extension,$archivos))
  8.         exit("Los archivos con extensión <b>$extension</b> no son archivos descargables.");
  9.     header("Content-type: application/octet-stream");
  10.     header("Content-Disposition: attachment; filename=$f");
  11.     $fp=fopen("$f", "r");
  12.     fpassthru($fp);
  13. ?>

Ahora, con el uso de la variable $archivos, podemos facilmente definir las extensiones de los archivos que deseamos permitir descargar.

Mas información en la entrada oficial