首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 輸出緩衝實現長時間任務實時進度顯示

     編輯:PHP 綜合知識

場景

執行耗時腳本(如數據遷移、報表生成、批量發送郵件)時,希望瀏覽器能實時看到進度輸出,而非等待腳本結束一次性顯示。

核心函數

  • ob_get_level() / ob_start():開啟/檢查輸出緩衝;
  • ob_flush():刷新 PHP 內部緩衝區到 Web 服務器;
  • flush():刷新 Web 服務器緩衝區到瀏覽器(需服務器支持,如 Apache mod_php、Nginx fastcgi_buffering off);
  • str_repeat(' ', 4096):填充足夠字節觸發瀏覽器渲染(部分瀏覽器需 > 1KB/8KB 才開始顯示)。

最小可行代碼

\n";
    // 實際業務邏輯
    sleep(1);
}
echo "輸出完畢!";

運行效果

第 1 次輸出
第 2 次輸出
...
第 10 次輸出
輸出完畢!

瀏覽器每隔 1 秒顯示一行,而非等待 10 秒一次性顯示。

生產環境常見阻礙及解決

層級配置/代碼說明
PHPoutput_buffering = Off (php.ini)或運行時 while(ob_get_level()) ob_end_clean();
PHP-FPMfastcgi_buffering off; (Nginx)關閉 FastCGI 緩衝,直接傳輸
Nginxproxy_buffering off; (反代時)關閉代理緩衝
ApacheSetOutputFilter DEFLATE 可能干擾壓縮模塊會緩衝輸出,需排除該路徑
瀏覽器需接收足夠字節(>1KB)才渲染用 str_repeat(' ', 4096) 填充

進階:封裝為 Progress 類

class Progress {
    public static function start() {
        while (ob_get_level()) ob_end_clean();
        echo str_repeat(' ', 4096);
        ob_end_flush();
        ob_implicit_flush(true);
    }
    public static function write($msg) {
        echo $msg . "
\n"; } public static function end($msg = '完成') { echo $msg; } } // 使用 Progress::start(); for ($i=1; $i<=5; $i++) { Progress::write("處理項目 #{$i}"); sleep(1); } Progress::end("全部完成");

替代方案

  1. WebSocket / Server-Sent Events (SSE):真雙向/單向推送,適合高實時要求;
  2. AJAX 輪詢:前端定時請求進度接口,後端從 Redis/DB 讀取進度;
  3. Comet / 長輪詢:服務器保持連接直到有數據返回。

對於簡單 CLI 腳本或內部工具,ob_flush + flush 方案最輕量、零依賴。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved