La documentación de PHP proporciona un buen ejemplo:
<?php
$file = 'monkey.gif';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
?>
EDITAR (Respuesta al comentario, explicación)
header('Content-Description: File Transfer');
No mostrar en el navegador, pero transferir el archivo.
header('Content-Type: application/octet-stream');
header('Content-Transfer-Encoding: binary');
El archivo es un archivo binario.
Los navegadores generalmente descargan archivos binarios, a menos que puedan mostrarlos.
header('Content-Disposition: attachment; filename='.basename($file));
Haga que el cuadro de diálogo de descarga muestre el nombre de archivo correcto.
Nota:puede usar cualquier nombre de archivo.
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
El navegador no debe almacenar en caché el archivo.
La caché podría causar problemas en caso de contenido dinámico.
header('Content-Length: ' . filesize($file));
Envíe el tamaño de archivo correcto al navegador,
de lo contrario, el navegador no podrá estimar el tiempo de transferencia.
ob_clean();
flush();
Asegúrese de que los encabezados se envíen al navegador antes de que comience la descarga.
readfile($file);
Envía el archivo al navegador.
exit;
Listo :)