Como forzar la descarga de archivos con PHP
En algunos contextos quizá es necesario que el usuario descargue un archivo pdf, xls, csv, etc, para ver más información en otros formatos legibles en el ordenador o incluso con el objetivo de ser impresos. Los navegadores de hoy en día muestran directamente algunos tipos de ficheros en el navegador antes de descargarlo y quizá puede ser molesto si lo que deseamos es descargarlo directamente nada más pulsar en el enlace o botón.
En este artículo vamos a ver un ejemplo de como conseguir tal efecto. Explicaremos un ejemplo para descargar directamente un archivo en formato csv que deberá estar previamente depositado en el servidor.
Allí donde deseemos dentro de la etiqueta <body> añadiremos un enlace del estilo:
Después tan solo necesitaremos añadir el código PHP de control de la descarga en el mismo fichero o donde controlemos las acciones del usuario:
if (isset($_GET['download_csv'])) {
$file_example = 'example.csv';
if (file_exists($file_example)) {
header('Content-Description: File Transfer');
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename='.basename($file_example));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file_example));
ob_clean();
flush();
readfile($file_example);
exit;
}
else {
echo 'Archivo no disponible.';
}
}
Lo primero que hacemos es comprobar que se haya pulsado en el enlace que contenga el parámetro de tipo GET «download_csv» con el simple objetivo de gestionar la descarga. Especificamos la ruta del fichero depositado en el servidor en la misma raiz del fichero que se ejecuta y comprobamos si existe para descargarlo.
A continuación especificamos información sobre el fichero para informar al navegador.
La función header() es imprescindible. Con ella conseguimos especificar e informar al navegador algunos datos relevantes para la descarga.
En este caso estamos indicando que:
- deseamos hacer una transferencia de archivo
- el tipo de archivo a procesar sea csv
- se trata de un archivo adjunto
- el tipo de codificación utilizada
Al final del script enviamos las cabeceras, limpiamos el buffer y abrimos el archivo que mostrará la ventana de descarga:
Si filename=’.basename($file_example) no tiene comillas dará problemas cuando el nombre de un archivo tiene comas. Es mejor delimitar el nombre del archivo así: filename=»‘.basename($file_example).'» ‘).
//para los que no les funciona prueben con esto
function download($fileName) {
if (file_exists($fileName)){
ob_clean();
header(‘Content-Description: File Transfer’);
header(‘Content-Type: text/csv’);
header(‘Content-Disposition: attachment; filename=’.basename($fileName));
header(‘Content-Transfer-Encoding: binary’);
header(‘Expires: 0’);
header(‘Cache-Control: must-revalidate’);
header(‘Pragma: public’);
header(‘Content-Length: ‘ . filesize($fileName));
ob_end_clean();
flush();
readfile($fileName);
return true;
}else{
$this->setMsg(__CLASS__.»::».__FUNCTION__, $fileName.» ¡Nose encontro el archivo!»);
return false;
}
}
Hola … el código me funcionaba bien hasta un par de días atrás … pero ahora cuando descargo los archivos y al abrirlos me dice que se bajo el archivo dañado … esto empezó después que el hosting cambió a otro servidor del proveedor. Me dice el proveedor que está el servidor en regla y todo actualizado usando php 7.4 … que podrá ser?
Hola,
Revisa si tu nuevo servidor permite realizar esta operación. Debes ponerte en contacto con ellos.
Saludos
Hola buenas, excelente el código funciona perfecto, pero al utilizarlo con Jquery y Ajax no hace la descarga ¿existe alguna solución?
Se agradece de antemano tu atencón
Hola,
Dejaré tu pregunta abierta por si alguien sabe la respuesta.
Jose Aguilar,
Saludos
Se acerca ,mucho a lo que quiero , pero como seria si en vez de un cvs fuese un pdf…gracias
Hola,
Entiendo que tan solo tienes que cambiar el:
header(‘Content-Type: text/csv’);
Según tu tipo de archivo.
Saludos
Tenia un problema que al descargar el archivo este se modificaba y se le agregaban al inicio espacios en blanco.
Esto se solucionó al usar estas funciones ob_clean(); flush() Muchas gracias!!!
como puedo sacar codigo fuente de php con la ruta
Hola,
Lamento decir que en este ejemplo no hay archivo para descargar pero todo el código está publicado y los puedes copiar y pegar en tu archivo php.
Saludos
Hola, ¡Saludos!
¿Es posible descargar más e un archivo (2 o 3) enviados desde un array?
Gracias de antemano,
Hola,
No sabría decirte. Tendrás que probar este código en un bucle para ver si es viable.
Saludos
La verdad es que si, depues de 2 dias con este problema de descarga el unico codigo que me ha servido ha sido el tuyo. muchas gracias por tu labor.
Disculpa mi comentario grosero, me funciono excelente!!!.
Gracias por el código. Fue el único código que sirvió, los demás que aparecen en Internet no sirven para una mierda.