使用 ob_flush 配合 flush 可以实现 php 大文件的强制下载,核心做法是关闭输出缓冲、设置正确的 http 响应头(如 content-type 和 content-disposition),然后以块为单位循环读取文件并立即输出。这样做可以避免内存溢出,并确保浏览器在接收数据时能正确触发下载行为。

如何配置响应头以确保浏览器触发下载而非预览
要让浏览器强制下载而不是在标签页中打开,必须设置 Content-Disposition: attachment 头。同时,对于大文件,建议禁用缓存并指定 Content-Length,以便浏览器显示进度条。如果未设置长度,部分浏览器可能无法正确显示下载进度或导致连接超时。

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($file) . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);为什么需要 ob_clean 和 flush 组合来分段发送
PHP 默认会缓冲输出,直到脚本执行完毕才发送给客户端。对于大文件,这会导致内存耗尽。通过调用 ob_clean() 清除内部缓冲区,再调用 flush() 将数据推送到 Web 服务器,可以实现流式传输。通常还需要设置 set_time_limit(0) 防止脚本超时,并使用 fopen 和 fread 分块读取文件,每读一块就输出一块。
立即学习“PHP免费学习笔记(深入)”;

set_time_limit(0);
$handle = fopen($file, 'rb');
if ($handle === false) {
die('Error opening file');
}
while (!feof($handle)) {
echo fread($handle, 1024 * 16);
ob_flush();
flush();
}
fclose($handle);当客户端中断连接时程序如何处理
在大文件下载过程中,如果用户取消下载或网络断开,PHP 脚本可能会继续运行直到文件读完,造成资源浪费。可以通过检查 connection_status() 或捕获异常来提前终止脚本。此外,Web 服务器(如 Nginx 或 Apache)也可能在检测到客户端断开后主动杀死 PHP 进程,具体行为取决于服务器配置。在实际代码中,可以在循环中加入对连接状态的检查,一旦检测到断开则立即退出循环并清理资源。



















