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

PHP header() 函數詳解:重定向、緩存控制、文件下載、Content-Type

     編輯:PHP 相關知識

核心規則

  • 必須在任何輸出前調用(HTML、空白、echo、print、BOM)。
  • PHP 4+ 可用 ob_start() 開啟輸出緩衝解決「headers already sent」。
  • header() 發送原始 HTTP 報頭,不自動換行。

常用報頭類型

1. 重定向

<?php
// 302 臨時重定向 (默認)
header('Location: https://example.com/login.php');
exit; // 關鍵:阻止後續代碼執行

// 301 永久重定向 (SEO 友好)
header('Location: https://example.com/new-url', true, 301);
exit;

// 相對路徑 (不推薦,RFC 7231 要求絕對 URI)
// header('Location: /login.php'); // 瀏覽器通常兼容
?>

2. 緩存控制

<?php
// 禁用緩存 (動態頁面、API)
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Cache-Control: post-check=0, pre-check=0', false); // HTTP/1.0
header('Pragma: no-cache'); // HTTP/1.0 兼容
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // 過去時間

// 靜態資源長期緩存 (一年)
header('Cache-Control: public, max-age=31536000, immutable');
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');

// 驗證緩存 (Last-Modified / ETag)
$lastMod = filemtime('data.json');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastMod) . ' GMT');
$etag = md5_file('data.json');
header('ETag: "' . $etag . '"');

if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && 
    strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $lastMod) {
    header('HTTP/1.1 304 Not Modified');
    exit;
}
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && 
    trim($_SERVER['HTTP_IF_NONE_MATCH'], '"') === $etag) {
    header('HTTP/1.1 304 Not Modified');
    exit;
}
?>

3. 文件下載

<?php
$file = '/var/www/files/report.pdf';
$filename = 'monthly_report.pdf';

if (!is_file($file)) {
    header('HTTP/1.1 404 Not Found');
    exit;
}

header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="' . rawurlencode($filename) . '"');
header('Content-Length: ' . filesize($file));
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes'); // 支持斷點續傳

// 大文件分塊輸出,避免內存溢出
$fp = fopen($file, 'rb');
while (!feof($fp)) {
    echo fread($fp, 8192);
    flush(); // 發送輸出緩衝
}
fclose($fp);
exit;
?>

4. Content-Type 常用值

類型值
JSONapplication/json; charset=utf-8
XMLapplication/xml; charset=utf-8
HTMLtext/html; charset=utf-8
純文本text/plain; charset=utf-8
CSVtext/csv; charset=utf-8
PDFapplication/pdf
ZIPapplication/zip
圖片image/jpeg, image/png, image/gif, image/webp
字體font/woff2, font/woff

5. 自定義報頭與 CORS

<?php
// CORS 跨域允許
header('Access-Control-Allow-Origin: https://app.example.com'); // 或 *
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400'); // 預檢緩存 1天

// 處理 OPTIONS 預檢請求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    exit(0);
}

// 自定義報頭 (X- 前綴慣例)
header('X-Request-ID: ' . uniqid());
header('X-RateLimit-Limit: 1000');
header('X-RateLimit-Remaining: 999');
?>

header() 參數詳解

header(string $header, bool $replace = true, int $http_response_code = 0): void
  • $replace:默認 true,替換同名報頭;false 允許同名多值(如多個 `Set-Cookie`)。
  • $http_response_code:強制設置狀態碼(PHP 5.4+ 可用 http_response_code())。

常見錯誤與調試

<?php
// 錯誤:輸出前有空白/BOM
// 輸出緩衝解決
ob_start();
// ... 業務代碼 ...
header('Location: /login');
ob_end_flush();

// 調試:查看已發送報頭
header('X-Debug: test');
$headers = headers_list();
print_r($headers);

// 檢查是否已發送
if (headers_sent($file, $line)) {
    error_log("Headers already sent in $file:$line");
}
?>

總結

  • 零輸出前調用是鐵律,善用 ob_start()。
  • 重定向必加 exit。
  • 緩存控制區分動態禁用與靜態長期,善用 Last-Modified/ETag 驗證。
  • 文件下載大文件分塊輸出 + flush,設置 Content-Length 支持進度條。
  • API 統一輸出 Content-Type: application/json; charset=utf-8。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved