長耗時腳本需實時向瀏覽器輸出進度,必須正確處理 PHP、Web Server、瀏覽器三層緩衝。本文給出生產可用的標準代碼模式。
<?php
// 1. 獲取 php.ini 緩衝大小,發送足夠空白字符觸發瀏覽器開始渲染
$buffer = ini_get('output_buffering');
echo str_repeat(' ', $buffer + 1024); // 佔位符,確保瀏覽器不等待
// 2. 關閉 PHP 內部緩衝(若 php.ini 開啟)
ob_end_flush();
// 3. 循環輸出 + 雙重刷新
for ($i = 1; $i <= 10; $i++) {
echo "第 $i 次輸出<br>\n";
ob_flush(); // 推送到 Web Server
flush(); // 推送到瀏覽器
sleep(1); // 模擬耗時操作
}
echo '輸出完畢!';
str_repeat(' ', ...):瀏覽器通常等待一定字節數(如 256B-1KB)才開始增量渲染,發送空白佔位符強制啟動ob_end_flush():關閉 PHP 內部緩衝層,使後續 ob_flush() 直接面向 SAPIob_flush() → flush(),不可顛倒sleep(1):模擬業務耗時,實際替換為真實邏輯| 層級 | 配置項 | 建議值 | 驗證方法 |
|---|---|---|---|
| PHP | output_buffering | Off / 0 | phpinfo() |
| PHP | zlib.output_compression | Off | phpinfo() |
| Apache | mod_deflate / mod_gzip | 關閉或排除該路徑 | .htaccess SetEnv no-gzip 1 |
| Nginx | fastcgi_buffering | off | location 配置 fastcgi_buffering off; |
| Nginx | proxy_buffering | off | location 配置 proxy_buffering off; |
| 瀏覽器 | 無特殊配置 | — | 開發者工具 Network 觀察流式載入 |
class RealtimeOutput {
public function __construct() {
$buf = ini_get('output_buffering');
echo str_repeat(' ', $buf + 1024);
@ob_end_flush();
}
public function write($msg) {
echo $msg;
ob_flush();
flush();
}
public function end($msg = '') {
if ($msg) $this->write($msg);
}
}
// 使用
$out = new RealtimeOutput();
for ($i = 1; $i <= 100; $i++) {
$out->write("處理第 $i 條記錄...
\n");
usleep(50000); // 0.05s
}
$out->end("全部完成!");