GZIP 壓縮需瀏覽器與伺服器雙端支援。流程:PHP 輸出緩衝 → 檢查瀏覽器 Accept-Encoding: gzip → gzencode() 壓縮 → 送出 Content-Encoding: gzip 標頭 → 瀏覽器自動解壓縮渲染。
<?php
// 1. 啟用輸出緩衝並指定回呼
ob_start('ob_gzip');
/* ... 產生大量輸出內容 ... */
for ($i = 0; $i < 100; $i++) {
echo '這裡是測試內容,重複以觀察壓縮效果。';
}
/* 2. 結束緩衝並輸出 (腳本結束會自動 flush) */
ob_end_flush();
/* 3. 壓縮回呼函數 */
function ob_gzip($content) {
// 條件:標頭未送出、zlib 已載入、瀏覽器支援 gzip
if (!headers_sent() && extension_loaded('zlib') &&
strpos($_SERVER['HTTP_ACCEPT_ENCODING'] ?? '', 'gzip') !== false) {
// 壓縮等級 9 (最高),附加註解以利除錯
$content = gzencode($content . "\n// 頁面已 GZIP 壓縮", 9);
// 必要回應標頭
header('Content-Encoding: gzip');
header('Vary: Accept-Encoding'); // 告訴 Proxy 依 Accept-Encoding 快取不同版本
header('Content-Length: ' . strlen($content));
}
return $content;
}
?>
ob_gzhandler (一鍵啟用)<?php
if (extension_loaded('zlib')) {
ob_start('ob_gzhandler');
}
?>
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>測試頁</title></head><body>
<?php for ($i = 0; $i < 10000; $i++) echo 'Hello World!'; ?>
</body></html>
<?php
if (extension_loaded('zlib')) {
ob_end_flush();
}
?>
ob_gzhandler 內建處理 Accept-Encoding 檢查、壓縮等級、標頭送出。zlib.output_compression INI 設定進一步簡化。將壓縮下移至 Nginx/Apache,PHP 完全不處理壓縮,效能最佳:
# Nginx
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_min_length 1000;
gzip_comp_level 6;
# Apache (mod_deflate)
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json
| 內容大小 | 未壓縮 | GZIP Level 9 | 壓縮率 |
|---|---|---|---|
| 重複文字 100 行 | 4.69 KB | 104 B | 97.8% ↓ |
| HTML 頁面 50 KB | 50 KB | 8 KB | 84% ↓ |
| JSON API 回應 20 KB | 20 KB | 3 KB | 85% ↓ |
Content-Encoding: gzip:告知瀏覽器內容已壓縮。Vary: Accept-Encoding:關鍵!讓 CDN/Proxy 針對支援/不支援 gzip 的客戶端分別快取,避免傳遞錯誤內容。Content-Length:壓縮後位元組數,利於連線復用與進度顯示。ob_start 必須在任何 echo、HTML、空白字元之前呼叫。ob_end_flush,否則壓縮不生效。Vary: Accept-Encoding 搭配隨機填充。content-encoding: gzip;線上工具 HTTP Compression Test。ob_gzhandler 快速驗證。