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

PHP header() 函數完全指南:常用場景、狀態碼、快取控制與下載輸出

     編輯:PHP 相關知識

header() 是 PHP 與 HTTP 協議溝通的核心橋樑。掌握它,就能精準控制瀏覽器行為:從編碼宣告、內容類型、快取策略、檔案下載,到 RESTful API 狀態碼回應。本文系統整理高頻用法,附帶最佳實踐與避坑指南。

⚠️ 核心鐵律:必須在任何輸出之前呼叫

<?php
// ❌ 錯誤:前面有空白/換行/BOM
header('Content-Type: application/json');

// ✅ 正確:腳本最頂端,無任何輸出
header('Content-Type: application/json; charset=utf-8');
echo json_encode(['status' => 'ok']);
// 輸出結束後不再有任何內容
?>

違反會拋出 Cannot modify header information - headers already sent 警告並導致 Header 失效。

一、內容類型與編碼宣告

場景Header 範例
HTML (UTF-8)header('Content-Type: text/html; charset=utf-8');
JSON APIheader('Content-Type: application/json; charset=utf-8');
XMLheader('Content-Type: application/xml; charset=utf-8');
CSV 下載header('Content-Type: text/csv; charset=utf-8');
圖片輸出header('Content-Type: image/jpeg'); / image/png
PDF 文件header('Content-Type: application/pdf');
ZIP 打包header('Content-Type: application/zip');

二、HTTP 狀態碼控制

<?php
// 200 成功(預設,通常可省略)
header('HTTP/1.1 200 OK');

// 301 永久重定向(SEO 遷移必備)
header('HTTP/1.1 301 Moved Permanently');
header('Location: https://new-domain.com/path');
exit();

// 302 暫時重定向
header('HTTP/1.1 302 Found');
header('Location: /login.php');
exit();

// 304 未修改(配合快取驗證)
header('HTTP/1.1 304 Not Modified');
exit();

// 400 錯誤請求
header('HTTP/1.1 400 Bad Request');
exit(json_encode(['error' => 'Invalid parameters']));

// 401 未授權(觸發瀏覽器登入彈窗)
header('HTTP/1.1 401 Unauthorized');
header('WWW-Authenticate: Basic realm="Admin Area"');
exit('Access denied');

// 403 禁止存取
header('HTTP/1.1 403 Forbidden');
exit('Permission denied');

// 404 找不到
header('HTTP/1.1 404 Not Found');
exit('Page not found');

// 500 伺服器錯誤
header('HTTP/1.1 500 Internal Server Error');
exit('Server error');

三、重定向與延遲跳轉

<?php
// 立即重定向
header('Location: https://example.com/');
exit();

// 延遲 5 秒跳轉(瀏覽器支援度較好)
header('Refresh: 5; url=https://example.com/');
echo '5 秒後自動跳轉...';

注意: Location 值建議使用絕對 URL;相對路徑在某些舊瀏覽器表現不一。

四、檔案下載標準模板

<?php
$filePath = '/data/exports/report-2024.xlsx';
$fileName = '年度報表.xlsx';

if (!is_file($filePath)) {
    header('HTTP/1.1 404 Not Found');
    exit('檔案不存在');
}

header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . rawurlencode($fileName) . '"');
header('Content-Length: ' . filesize($filePath));
header('Content-Transfer-Encoding: binary');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Expires: 0');

readfile($filePath); // 直接輸出檔案流,不佔用 PHP 記憶體
exit();

關鍵點:

  • rawurlencode() 處理中文檔名,避免瀏覽器亂碼。
  • readfile() 直接將檔案流輸出至輸出緩衝,大檔案不會撐爆 memory_limit。
  • Nginx + PHP-FPM 環境建議開啟 X-Accel-Redirect (X-Sendfile) 讓 Nginx 直接傳檔,效能更高。

五、快取控制策略

目標Header 組合
完全禁止快取(動態 API、敏感頁面)
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
允許快取 1 小時(靜態資源、公開 API)
header('Cache-Control: public, max-age=3600');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 3600) . ' GMT');
協商快取(需配合 ETag/Last-Modified)
header('Cache-Control: no-cache, must-revalidate');
header('ETag: "' . md5($content) . '"');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $mtime) . ' GMT');

六、其他實用 Header

  • 隱藏 PHP 版本: header('X-Powered-By: ');(或 php.ini 設 expose_php = Off)
  • 允許跨域 (CORS): header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); header('Access-Control-Allow-Headers: Content-Type, Authorization');
  • Content Security Policy: header("Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com;");
  • 防點擊劫持: header('X-Frame-Options: DENY'); 或 SAMEORIGIN
  • MIME 嗅探保護: header('X-Content-Type-Options: nosniff');

七、常見錯誤與除錯技巧

  1. 多次 header() 覆蓋: 同名 Header 後者覆蓋前者,若需多值(如多個 Set-Cookie)使用 header('Set-Cookie: ...', false) 第二參數 false 表示不替換。
  2. BOM 頭導致 Header 失效: 以 UTF-8 without BOM 儲存檔案(VS Code 右下角切換編碼)。
  3. 輸出緩衝干擾: ob_start() 可暫存輸出,但在 Header 發送前務必 ob_end_clean() 或 ob_end_flush()。
  4. 檢查實際發送的 Header: 瀏覽器 DevTools → Network → Headers;或 CLI curl -I url。

總結

header() 是 PHP 開發者與 HTTP 協議對話的鑰匙。熟練掌握內容類型、狀態碼、快取、下載、安全 Header 的組合拳,能讓你的 API 更標準、頁面更安全、檔案傳輸更可靠。記住:無輸出前發送、善用 exit()、驗證實際回應,是避坑三寶。

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