長時間運行的 PHP 腳本(如爬蟲、導出、視頻轉碼)需要即時將進度輸出到瀏覽器,而非等待腳本結束一次性輸出。關鍵在於**關閉輸出緩衝、開啟隱式刷新、適當填充內容長度**。
<?php
header("Content-type: text/html; charset=utf-8");
set_time_limit(0); // 移除執行時間限制
ob_end_clean(); // 清除並關閉輸出緩衝
ob_implicit_flush(1); // 開啟隱式刷新:每次 echo/print 直接發送
// 部分瀏覽器需內容達到一定長度才渲染,填充佔位符
$pad = str_repeat("", 200);
while (true) {
echo $pad . 'hello sjolzy.cn
';
sleep(1);
// 可選:ob_flush(); flush(); // 視服務器配置可能需要
}
| 函數 | 作用 |
|---|---|
ob_end_clean() | 刪除當前輸出緩衝區內容並關閉緩衝,防止內容被攔截。 |
ob_implicit_flush(true) | 開啟隱式刷新:後續每個輸出語句(echo/print)自動調用 flush()。 |
flush() | 將 PHP 緩衝區內容推送到 Web Server(Apache/Nginx),再由 Server 發送給瀏覽器。 |
ob_flush() | 僅刷新 PHP 內部輸出緩衝區,需配合 flush() 完整推送到客戶端。 |
proxy_buffering on,會緩存 FastCGI 響應體。需在 location 配置 proxy_buffering off; 或響應頭發送 X-Accel-Buffering: no。SetEnv no-gzip 1。str_repeat 填充。fastcgi_request_buffering off 關閉(需 FPM 配置)。class RealTimeOutput {
public static function init($charset = 'utf-8') {
header("Content-Type: text/html; charset=$charset");
set_time_limit(0);
@ob_end_clean();
@ob_implicit_flush(true);
// 禁用 Nginx/Apache 緩衝
header('X-Accel-Buffering: no');
}
public static function write($msg) {
echo $msg;
@ob_flush();
@flush();
}
public static function pad($len = 1024) {
echo str_repeat(' ', $len); // 空白填充觸發瀏覽器渲染
}
}
// 使用
RealTimeOutput::init();
for ($i = 1; $i <= 100; $i++) {
RealTimeOutput::write("進度: $i%
");
RealTimeOutput::pad();
sleep(1);
}
掌握輸出緩衝鏈路(PHP -> Web Server -> 瀏覽器),在每一層關閉緩衡或強制刷新,才能實現真正的實時輸出。