Este es mi script favorito de descarga de PHP. Antes usaba un método diferente más simple, hasta que un cliente quería permitir a los visitantes de su sitio descargar un archivo grande de un directorio protegido por contraseña. El script PHP funciona en servidores web Apache para todo tipo de archivos. He usado este script para descargas de archivos incluso más grandes que 500MB. El encabezado de control de la caché se utiliza para forzar una descarga de archivos de texto u otros archivos, incluso si se abren por defecto dentro de su navegador web.
¿Cómo se usa el script de descarga de archivos PHP?
Crea un script PHP, llámalo «download.php» y copia/pega el siguiente código:
<?php
ignore_user_abort(true);
set_time_limit(0); // deshabilitar el límite de tiempo para esta ejecución
$path = "/absolute_path_to_your_files/"; // cambiar la ruta para que se ajuste a la estructura de los documentos de su sitio web
$dl_file = preg_replace("([^\w\s\d\-_~,;:\[\]\(\).]|[\.]{2,})", '', $_GET['download_file']); // simple file name validation
$dl_file = filter_var($dl_file, FILTER_SANITIZE_URL); // Eliminar (más) caracteres no válidos
$fullPath = $path.$dl_file;
if ($fd = fopen ($fullPath, "r")) {
$fsize = filesize($fullPath);
$path_parts = pathinfo($fullPath);
$ext = strtolower($path_parts["extension"]);
switch ($ext) {
case "pdf":
header("Content-type: application/pdf");
header("Content-Disposition: attachment; filename=\"".$path_parts["basename"]."\""); // usar 'attachment' para forzar la descarga de un archivo
break;
// añadir más encabezados para otros tipos de contenido aquí
default;
header("Content-type: application/octet-stream");
header("Content-Disposition: filename=\"".$path_parts["basename"]."\"");
break;
}
header("Content-length: $fsize");
header("Cache-control: private"); //usar esto para abrir los archivos directamente
while(!feof($fd)) {
$buffer = fread($fd, 2048);
echo $buffer;
}
}
fclose ($fd);
exit;
Crear en su página web enlaces para todos los archivos que están en un directorio protegido por contraseña o en un directorio por encima del directorio raíz del sitio web. Utiliza para nuestro ejemplo la siguiente URL de descarga:
<?php
echo '
<a href="http://mydomain.com/download.php?download_file=some_file.pdf">PHP download file</a>';
Características del archivo de descarga PHP:
El nombre del archivo, que se pasa a través de la cadena de consulta, se verifica usando la función de PHP preg_replace() y filter_var()
Para hacer el script más seguro, uso la función PHP pathinfo() para analizar la ruta del archivo, si esto sucede con éxito, el script continuará el proceso de manejo de archivos.
El script de descarga de archivos también es útil para archivos más grandes (¡usando este script he descargado archivos de más de 500MB!).
Demostración del Script
La página de demostración muestra los ejemplos de código PHP para la carga y descarga de archivos y las funciones de directorio PHP para mostrar los archivos en un menú SELECT.
PHP descarga archivos de una base de datos MySQL
El código de descarga PHP no oculta el nombre del archivo y en algunas situaciones podría ser mejor utilizar una cadena o ID único como clave para la descarga del archivo. En el siguiente ejemplo, usaré una cadena para recibir el nombre de un archivo que se almacena dentro de una base de datos MySQL segura. Digamos que tenemos una simple tabla de base de datos con sólo dos columnas para el ID y el nombre del archivo. El código del archivo download.php es casi el mismo y sólo la primera parte es diferente:
<?php
ignore_user_abort(true);
set_time_limit(0);
$path = "/absolute_path_to_your_files/";
$secret = 'your-secret-string';
if (isset($_GET['fid']) && preg_match('/^([a-f0-9]{32})$/', $_GET['fid'])) {
$db = new mysqli('localhost', 'username', 'password', 'databasename');
$result = $db->query(sprintf("SELECT filename FROM mytable WHERE MD5(CONCAT(ID, '%s')) = '%s'", $secret, $db->real_escape_string($_GET['fid'])));
if ($result_>num_rows == 1) {
$obj = $result->fetch_object();
$fullPath = $path.$obj->filename;
if ($fd = fopen ($fullPath, "r")) {
//
// the other PHP download code
//
}
fclose ($fd);
exit;
} else {
die('no match');
}
} else {
die('missing file ID');
}
¿Cómo usar ese código de descarga PHP/MySQL?
En el primer ejemplo usé el nombre del archivo dentro de la URL de descarga. Como estoy usando la encriptación md5() con $secreto como «el salt», necesito construir la URL de descarga de mi archivo de forma diferente:
<?php
$file_id = 123; // or something else you got from your MySQL database
$slug = md5($secret.$file_id);
echo '
<a href="http://mydomain.com/dowload.php?fid='.$slug.'">PHP download file via MySQL</a>';
He publicado el código de ejemplo de descarga de PHP para explicar cómo escribir un script de descarga de archivos PHP. Si realmente necesitas proteger tus descargas, necesitas negar el acceso directo a la ubicación del archivo usando directivas de Apache o reglas de .htaccess. Utilice slugs más seguros para recibir un nombre de archivo de su base de datos. Por ejemplo, también puedes cifrar la clave de la fila de la base de datos.