PHP Conference Japan 2024

header

(PHP 4, PHP 5, PHP 7, PHP 8)

header傳送原始 HTTP 標頭

說明

header(string $header, bool $replace = true, int $response_code = 0): void

header() 用於傳送原始 HTTP 標頭。 請參閱 » HTTP/1.1 規範 以取得更多關於 HTTP 標頭的資訊。

請記住,header() 必須在任何實際輸出傳送之前呼叫,無論是透過一般的 HTML 標籤、檔案中的空白行,或來自 PHP。 讀取包含 includerequire 函式,或其他檔案存取函式的程式碼,並且在呼叫 header() 之前有空格或空行輸出,這是一個非常常見的錯誤。 當使用單一 PHP/HTML 檔案時,也會發生相同的問題。

<html>
<?php
/* 這會產生錯誤。 請注意上面的輸出,
* 這是 header() 呼叫之前 */
header('Location: http://www.example.com/');
exit;
?>

參數

header

header

標頭字串。

有兩個特殊情況的標頭呼叫。 第一個是以字串 "HTTP/" 開頭的標頭(大小寫不重要),它將用於計算要傳送的 HTTP 狀態碼。 例如,如果您已設定 Apache 使用 PHP 腳本來處理遺失檔案的要求(使用 ErrorDocument 指令),您可能需要確保您的腳本產生適當的狀態碼。

<?php
// 這個範例說明 "HTTP/" 特殊情況
// 在典型的使用案例中,較好的替代方法包括:
// 1. header($_SERVER["SERVER_PROTOCOL"] . " 404 Not Found");
// (為了覆蓋仍然使用 HTTP/1.0 的客戶端的 http 狀態訊息)
// 2. http_response_code(404); (使用預設訊息)
header("HTTP/1.1 404 Not Found");
?>

第二個特殊情況是 "Location:" 標頭。 它不僅將此標頭傳送回瀏覽器,而且還會傳回 REDIRECT (302) 狀態碼給瀏覽器,除非已設定 2013xx 狀態碼。

<?php
header
("Location: http://www.example.com/"); /* 重新導向瀏覽器 */

/* 確保在重新導向時,下面的程式碼不會被執行。 */
exit;
?>

replace

選用的 replace 參數表示標頭是否應該取代先前的類似標頭,或新增第二個相同類型的標頭。 預設情況下,它會取代,但如果您傳入 false 作為第二個引數,您可以強制使用多個相同類型的標頭。 例如

<?php
header
('WWW-Authenticate: Negotiate');
header('WWW-Authenticate: NTLM', false);
?>

response_code

強制將 HTTP 回應碼設為指定的值。 請注意,只有當 header 不為空時,此參數才會生效。

傳回值

不傳回任何值。

錯誤/例外

如果無法排定傳送標頭,header() 會發出 E_WARNING 等級的錯誤。

範例

範例 1:下載對話框

如果您希望提示使用者儲存您傳送的資料,例如產生的 PDF 檔案,您可以使用 » Content-Disposition 標頭來提供建議的檔案名稱,並強制瀏覽器顯示儲存對話框。

<?php
// 我們將輸出 PDF
header('Content-Type: application/pdf');

// 它將被命名為 downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');

// PDF 來源在 original.pdf 中
readfile('original.pdf');
?>

範例 2:快取指示

PHP 腳本通常會產生動態內容,這些內容不得由客戶端瀏覽器或伺服器和客戶端瀏覽器之間的任何 Proxy 快取。 許多 Proxy 和客戶端可以透過以下方式強制停用快取

<?php
header
("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // 過去的時間
?>
:

注意

您可能會發現,即使您沒有輸出以上的所有標頭,您的頁面也不會被快取。 使用者可以為其瀏覽器設定許多選項,這些選項會變更其預設快取行為。 透過傳送以上標頭,您應該覆寫任何可能導致快取腳本輸出的設定。

此外,當使用工作階段時,可以使用 session_cache_limiter()session.cache_limiter 設定選項來自動產生正確的快取相關標頭。

範例 3:設定 Cookie

setcookie() 提供了一種方便的方式來設定 Cookie。 若要設定包含 setcookie() 不支援的屬性的 Cookie,可以使用 header()

例如,以下程式碼會設定一個包含 Partitioned 屬性的 Cookie。

<?php
header
('Set-Cookie: name=value; Secure; Path=/; SameSite=None; Partitioned;');
?>

<?php
header
("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // 過去的時間
?>
:

注意事項

<?php
header
("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // 過去的時間
?>
:

只有在使用支援它們的 SAPI 時,才能存取和輸出標頭。

<?php
header
("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // 過去的時間
?>
:

您可以使用輸出緩衝來解決這個問題,其額外負擔是您所有傳送到瀏覽器的輸出都緩衝在伺服器中,直到您傳送它為止。 您可以在腳本中呼叫 ob_start()ob_end_flush(),或在您的 php.ini 或伺服器設定檔案中設定 output_buffering 設定指令。

<?php
header
("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // 過去的時間
?>
:

無論實際的 header() 呼叫是否為第一個,HTTP 狀態標頭行始終是第一個傳送到客戶端的。 除非 HTTP 標頭已經傳送,否則隨時可以呼叫具有新狀態行的 header() 來覆寫該狀態。

<?php
/* 重新導向至目前目錄下請求的不同頁面 */
$host = $_SERVER['HTTP_HOST'];
$uri = rtrim(dirname($_SERVER['PHP_SELF']), '/\\');
$extra = 'mypage.php';
header("Location: http://$host$uri/$extra");
exit;
?>

<?php
header
("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // 過去的時間
?>
:

即使啟用了 session.use_trans_sid,Session ID 也不會透過 Location 標頭傳遞。它必須使用 SID 常數手動傳遞。

另請參閱

新增註解

使用者貢獻的註解 26 個註解

mjt at jpeto dot net
15 年前
我強烈建議您使用

header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");

而不是

header("HTTP/1.1 404 Not Found");

當我(意外地)加入 "HTTP/1.1 200 Ok" 標頭時,我在 Apache/2.0.59 (Unix) 回應 HTTP/1.0 時遇到了很大的麻煩。

大多數頁面都正確顯示,但在某些頁面上,apache 會在其中新增奇怪的內容

頁面頂端(在我的 php 腳本的任何輸出之前)的 4 位數十六進位程式碼,似乎是一種校驗和,因為它在頁面和瀏覽器之間會變更。(相同頁面和瀏覽器使用相同程式碼)

頁面底部(在我 php 腳本的完整輸出之後)的 "0"

我花了一段時間才找出 HTTP 標頭中的錯誤協定。
Marcel G
14 年前
這個問題在網路上被問了很多次,但在 php.net 的文件中找不到答案...

如果您想重新導向使用者並告知他將被重新導向,例如「您將在 5 秒內重新導向。如果沒有,請按一下這裡。」,您不能使用 header( 'Location: ...' ),因為您不能在傳送標頭之前傳送任何輸出。

因此,您必須使用 HTML meta refresh 功能,或者使用以下程式碼

<?php
header
( "refresh:5;url=wherever.php" );
echo
'您將在 5 秒內重新導向。如果沒有,請按一下 <a href="wherever.php">這裡</a>。';
?>

希望對某些人有幫助
Dylan at WeDefy dot com
17 年前
使重新導向永久或暫時的一種快速方法是利用 header() 中的 $http_response_code 參數。

<?php
// 301 永久移動
header("Location: /foo.php",TRUE,301);

// 302 找到
header("Location: /foo.php",TRUE,302);
header("Location: /foo.php");

// 303 參見其他
header("Location: /foo.php",TRUE,303);

// 307 暫時重新導向
header("Location: /foo.php",TRUE,307);
?>

HTTP 狀態碼會變更瀏覽器和機器人處理重新導向的方式,因此,如果您使用 header(Location:),最好同時設定狀態碼。瀏覽器通常每次都會重新要求 307 頁面,將 302 頁面快取至工作階段,並將 301 頁面快取更長時間,甚至是無限期。搜尋引擎通常會將「頁面排名」傳輸到 301 重新導向的新位置,但不會傳輸到 302、303 或 307。如果未指定狀態碼,header('Location:') 預設為 302。
mandor at mandor dot net
18 年前
當使用 PHP 輸出影像時,它不會被客戶端快取,因此如果您不希望他們每次重新載入頁面時都下載影像,您將需要模擬部分 HTTP 協定。

以下是如何操作

<?php

// 測試影像。
$fn = '/test/foo.png';

// 取得客戶端傳送的標頭。
$headers = apache_request_headers();

// 檢查客戶端是否正在驗證其快取,以及是否為最新狀態。
if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == filemtime($fn))) {
// 客戶端的快取為最新狀態,因此我們只回應「304 Not Modified」。
header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($fn)).' GMT', true, 304);
} else {
// 影像未快取或快取已過時,我們回應「200 OK」並輸出影像。
header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($fn)).' GMT', true, 200);
header('Content-Length: '.filesize($fn));
header('Content-Type: image/png');
print
file_get_contents($fn);
}

?>

這樣 foo.png 就會被客戶端正確快取,而且您將節省頻寬。:)
Emmanuel Chazard
1 年前
如果您使用 header() 來允許使用者下載檔案,則檢查腳本本身的編碼非常重要。您的腳本應以 UTF-8 編碼,但絕對不能以 UTF-8-BOM 編碼!BOM 的存在會變更使用者收到的檔案。讓以下腳本執行

<?php

$content
= file_get_contents('test_download.png') ;
$name = 'test.png' ;
$size = strlen($content) ;

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Cache-Control: no-cache, must-revalidate');
header('Expires: 0');
header('Content-Disposition: attachment; filename="'.$name.'"');
header('Content-Length: ' . $size);
header('Pragma: public');

echo
$content ;

?>

不論 test_download.png 的編碼為何,當此 PHP 腳本以 UTF-8-BOM 編碼時,使用者收到的內容會有所不同
- ZWNBSP 位元組 (U+FEFF) 會新增至檔案的開頭
- 檔案內容會被截斷!!!
如果它是二進位檔案(例如影像、專有格式),則檔案會變得無法讀取。
php at ober-mail dot de
4 年前
自 PHP 5.4 起,可以使用 `http_response_code()` 函式來設定回應碼,而不是使用 `header()` 函式,後者還需要設定正確的協定版本(如其他留言中所見,這可能會導致問題)。
bebertjean at yahoo dot fr
16 年前
如果使用 'header' 函式來下載檔案,特別是當您將檔名作為變數傳遞時,請記得用雙引號將檔名括起來,否則只要檔名中有空格,在 Firefox 中就會出現問題。

所以不要輸入

<?php
header
("Content-Disposition: attachment; filename=" . basename($filename));
?>

您應該輸入

<?php
header
("Content-Disposition: attachment; filename=\"" . basename($filename) . "\"");
?>

如果您不這樣做,當使用者點擊名為「Example file with spaces.txt」的檔案連結時,Firefox 的「另存新檔」對話框會將其名稱顯示為「Example」,並且沒有副檔名。

請參閱名為「Filenames_with_spaces_are_truncated_upon_download」的頁面,網址為
http://kb.mozillazine.org/ 以取得更多資訊。(抱歉,該網站不允許我張貼這麼長的連結...)
David Spector
3 年前
請注意,無論是在 PHP、瀏覽器還是網頁開發人員工具中,`header` 命令都沒有錯誤檢查。

如果您使用類似 "header('text/javascript');" 的程式碼來設定 PHP 回應文字的 MIME 類型(例如針對回傳或包含的資料),您將會遇到未診斷的失敗。

正確的 MIME 設定函式是 "header('Content-type: text/javascript');"。
yjf_victor
8 年前
根據 RFC 6226 (https://tools.ietf.org/html/rfc6266),傳送帶編碼的 Content-Disposition Header 的唯一方法是

Content-Disposition: attachment;
filename*= UTF-8''%e2%82%ac%20rates

為了向後相容性,應傳送的內容為

Content-Disposition: attachment;
filename="EURO rates";
filename*=utf-8''%e2%82%ac%20rates

因此,我們應該使用

<?php
$filename
= '中文文件名.exe'; // 中文字元的檔名

$contentDispositionField = 'Content-Disposition: attachment; '
. sprintf('filename="%s"; ', rawurlencode($filename))
.
sprintf("filename*=utf-8''%s", rawurlencode($filename));

header('Content-Type: application/octet-stream');

header($contentDispositionField);

readfile('file_to_download.exe');
?>

我已在 IE6-10、Firefox 和 Chrome 中測試過此程式碼。
sk89q
16 年前
您可以使用 HTTP 的 etag 和上次修改日期,以確保您沒有將瀏覽器已經快取的資料傳送出去。

<?php
$last_modified_time
= filemtime($file);
$etag = md5_file($file);

header("Last-Modified: ".gmdate("D, d M Y H:i:s", $last_modified_time)." GMT");
header("Etag: $etag");

if (@
strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time ||
trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) {
header("HTTP/1.1 304 Not Modified");
exit;
}
?>
nospam at nospam dot com
8 年前
<?php

// 使用
header('Location: /target.php', true, $code) 將使用者轉導到另一個頁面時的回應碼行為:

$code = 301;
// 當舊頁面已被「永久移動,且任何未來的請求都應改為傳送到目標頁面時使用。PageRank 可能會轉移。」

$code = 302; (預設)
// 「臨時重新導向,因此只有在 Cache-Control 或 Expires 標頭欄位中指示時,才會快取頁面。」

$code = 303;
// 「此方法主要用於允許 POST 啟動的指令碼將使用者代理重新導向到選定的資源。新的 URI 並非原始請求資源的替代參考,且不會被快取。」

$code = 307;
// 請注意,當在提交表單後使用 POST 時,它會將張貼的值轉移到下一頁,例如,如果 target.php 包含表單處理指令碼,則它會再次處理提交的資訊!

// 換句話說,如果永久,則使用 301;如果臨時,則使用 302;如果是由已提交表單產生的結果頁面,則使用 303。
// 如果表單處理指令碼已移動,則可能會使用 307。

?>
tim at sharpwebdevelopment dot com
6 年前
對 PHP 初學者而言,`header` 的呼叫可能會產生誤導。
當提到「header 呼叫」時,指的是檔案的最左上方位置,而不是「header()」函式本身。
「<?php」的開始標籤必須放置在任何其他內容之前,甚至是空白字元。
David
7 年前
似乎說 URI 必須是絕對的註解已經過時。在 https://en.wikipedia.org/wiki/HTTP_location 上找到

「HTTP 1.1 規格的過時版本 (IETF RFC 2616) 要求重新導向必須使用完整的絕對 URI。[2] IETF HTTP 工作群組發現,大多數流行的網頁瀏覽器都能容忍傳遞相對 URL [3],因此,更新後的 HTTP 1.1 規格 (IETF RFC 7231) 放寬了原始限制,允許在 Location 標頭中使用相對 URL。」
ben at indietorrent dot org
12 年前
請注意,如果包含以下任何標頭,透過加密連線 (SSL/TLS) 將二進位檔案傳送到使用者代理 (瀏覽器) 將會在 IE (Internet Explorer) 版本 5、6、7 和 8 中失敗

Cache-control:no-store
Cache-control:no-cache

請參閱:http://support.microsoft.com/kb/323308

解決方法:不要傳送這些標頭。

此外,請注意,IE 版本 5、6、7 和 8 會對已壓縮的檔案進行雙重壓縮,且無法正確還原此過程,因此 ZIP 檔案和類似的檔案在下載時會損壞。

解決方法:針對這些特定版本的 IE 停用壓縮 (除了 text/html 之外),例如使用 Apache 的「BrowserMatch」指令。以下範例會停用所有 IE 版本中的壓縮

BrowserMatch ".*MSIE.*" gzip-only-text/html
chris at ocproducts dot com
7 年前
請注意,`session_start` 可能會覆寫您的自訂快取標頭。
為了解決此問題,您需要呼叫

session_cache_limiter('');

...在您設定自訂快取標頭之後。它會告知 PHP 工作階段程式碼不要進行任何自己的快取標頭變更。
jp at webgraphe dot com
21 年前
建議在陳述式之前呼叫 `session_write_close()`

<?php
header
("Location: URL");
exit();
?>

如果您想要確保在繼續重新導向之前工作階段已更新。

我們遇到一種情況,由於先前的指令碼沒有時間更新 (我們使用了資料庫處理常式),導致重新導向所存取的指令碼無法正確載入工作階段。

JP.
shutout2730 at yahoo dot com
16 年前
必須注意,標頭實際上是在第一個位元組輸出到瀏覽器時傳送的。如果您在指令碼中替換標頭,這表示 echo/print 陳述式和輸出緩衝區的放置位置可能會影響傳送的標頭。就重新導向而言,如果您在傳送標頭後忘記終止您的指令碼,則新增緩衝區或傳送字元可能會變更將使用者傳送到的頁面。

這會重新導向到 2.html,因為第二個標頭會取代第一個。

<?php
header
("location: 1.html");
header("location: 2.html"); //取代 1.html
?>

這會重新導向到 1.html,因為一旦發生 echo,就會傳送標頭。您也不會看到任何「已傳送標頭」的錯誤,因為瀏覽器會在顯示錯誤之前追蹤重新導向。

<?php
header
("location: 1.html");
echo
"send data";
header("location: 2.html"); //已傳送 1.html
?>

將先前的範例包裝在輸出緩衝區中實際上會變更指令碼的行為!這是因為標頭直到輸出緩衝區刷新後才會傳送。

<?php
ob_start
();
header("location: 1.html");
echo
"send data";
header("location: 2.html"); //取代 1.html
ob_end_flush(); //現在傳送標頭
?>
Refugnic
14 年前
我的檔案是壓縮狀態 (bz2)。當使用者點擊連結時,我希望他們取得的是未壓縮版本的檔案。

在解壓縮檔案後,我遇到了問題,即使我告訴對話框「永遠對此檔案類型執行此操作」,下載對話框仍然會一直彈出。

我發現問題出在標頭指令 'Content-Disposition',尤其是 'attachment' 指令。

如果您希望瀏覽器模擬一個指向檔案的普通連結,可以將 'attachment' 更改為 'inline' 或完全省略它,這樣就可以了。

我花了一段時間才弄清楚這一點,我希望這能幫助其他遇到相同問題的人。
dev at omikrosys dot com
15 年前
只是想通知大家,不要混淆 Content-Transfer-Encoding 和 Content-Encoding。

Content-Transfer-Encoding 指定在 HTTP 協定內傳輸資料時使用的編碼,例如原始二進位或 base64。(二進位比 base64 更緊湊,base64 有 33% 的額外負擔)。
例如,使用:- header('Content-Transfer-Encoding: binary');

Content-Encoding 用於對內容/資料應用 gzip 壓縮之類的處理。
例如,使用:- header('Content-Encoding: gzip');
razvan_bc at yahoo dot com
6 年前
<?php
/* 這會產生錯誤。請注意上面的輸出,
* 它是在 header() 呼叫之前 */
header('Location: http://www.example.com/');
exit;
?>

這個範例很好,但是當你使用 "exit" 時,解析器仍然會繼續運作以決定下一步要做什麼。"exit" 的動作應該是這樣 (因為如果你檢查手冊,exit 在其他情況下也有效)。
所以我的重點是:你應該使用
<?php

header
('Location: http://www.example.com/');
die();

?>
因為 die 函式的作用只是停止腳本,沒有其他需要解釋的地方,而且你選擇中斷腳本動作的範圍會很快完成!

還有很多其他範例的情況,對於腳本的小部分來說,正確的選擇在你編寫 PHP 框架時會產生差異!

感謝 Rasmus Lerdorf 和他的團隊整理出不常見的 PHP 功能,PHP 7 真是太棒了!!!!!
scott at lucentminds dot com
15 年前
如果您想要移除一個標頭並防止它作為標頭回應的一部分傳送,只需在標頭名稱後提供空值作為標頭值即可。例如...

預設情況下,PHP 總是會傳回以下標頭

"Content-Type: text/html"

您的整個標頭回應會看起來像這樣

HTTP/1.1 200 OK
Server: Apache/2.2.11 (Unix)
X-Powered-By: PHP/5.2.8
Date: Fri, 16 Oct 2009 23:05:07 GMT
Content-Type: text/html; charset=UTF-8
Connection: close

如果您呼叫標頭名稱但不帶值,如下所示...

<?php

header
( 'Content-Type:' );

?>

您的標頭現在看起來像這樣

HTTP/1.1 200 OK
Server: Apache/2.2.11 (Unix)
X-Powered-By: PHP/5.2.8
Date: Fri, 16 Oct 2009 23:05:07 GMT
Connection: close
Anonymous
15 年前
我只是想補充一點,因為我看到這裡有很多格式錯誤的標頭。

1. 所有使用的標頭的第一個字母都是大寫,所以你必須遵循這一點。例如

Location,而不是 location
Content-Type,而不是 content-type,也不是 CONTENT-TYPE

2. 然後必須有冒號和空格,像這樣

正確:header("Content-Type: text/plain");
錯誤:header("Content-Type:text/plain");

3. Location 標頭必須是具有協定、網域、埠號、路徑等的絕對 URI。

正確:header("Location: http://www.example.com/something.php?a=1");

4. 不允許使用相對 URI

錯誤:Location: /something.php?a=1
錯誤:Location: ?a=1

這會讓代理伺服器和 HTTP 客戶端更開心。
mzheng[no-spam-thx] at ariba dot com
16 年前
對於大型檔案(100+ MB),我發現盡快刷新檔案內容至關重要,否則下載對話框要過很久才會顯示或根本不顯示。

<?php
header
("Content-Disposition: attachment; filename=" . urlencode($file));
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Description: File Transfer");
header("Content-Length: " . filesize($file));
flush(); // 這實際上沒什麼關係。

$fp = fopen($file, "r");
while (!
feof($fp))
{
echo
fread($fp, 65536);
flush(); // 這對於大型下載來說至關重要
}
fclose($fp);
?>
Vinay Kotekar
9 年前
以 ANSI 格式儲存 PHP 檔案沒有問題,但由於各種原因,當以 UTF-8 格式儲存檔案時,請記得儲存檔案時不要帶有任何 BOM (位元組順序標記) 支援。
否則,您將會遇到標頭無法正確傳送的問題
例如。
<?php header("Set-Cookie: name=user");?>

會產生類似這樣的結果:-

Warning: Cannot modify header information - headers already sent by (output started at C:\www\info.php:1) in C:\www\info.php on line 1
Cody G.
14 年前
經過大量的研究和測試後,我想分享我關於 Internet Explorer 和檔案下載問題的發現。

看看這段程式碼,它複製了正常下載 JavaScript 的情況

<?php
if(strstr($_SERVER["HTTP_USER_AGENT"],"MSIE")==false) {
header("Content-type: text/javascript");
header("Content-Disposition: inline; filename=\"download.js\"");
header("Content-Length: ".filesize("my-file.js"));
} else {
header("Content-type: application/force-download");
header("Content-Disposition: attachment; filename=\"download.js\"");
header("Content-Length: ".filesize("my-file.js"));
}
header("Expires: Fri, 01 Jan 2010 05:00:00 GMT");
if(
strstr($_SERVER["HTTP_USER_AGENT"],"MSIE")==false) {
header("Cache-Control: no-cache");
header("Pragma: no-cache");
}
include(
"my-file.js");
?>

現在讓我來解釋一下

我首先檢查是否為 IE,如果不是 IE,我將 Content-type(區分大小寫)設定為 JS,並將 Content-Disposition(從現在開始,每個標頭都區分大小寫)設定為 inline,因為大多數 IE 以外的瀏覽器都喜歡將 JS 行內顯示。(使用者可以變更設定)。某些瀏覽器需要 Content-Length 標頭才能啟用下載方塊。然後,如果是 IE,有時需要 "application/force-download" 的 Content-type 來顯示下載方塊。如果您不希望您的 PDF 在瀏覽器中顯示(在 IE 中),請使用此方法。我在此處使用它來確保方塊開啟。無論如何,我將 Content-Disposition 設定為 attachment,因為我已經知道方塊會出現。然後我再次設定 Content-Length。

現在,這是我的重點。我只在不是 IE 的情況下才傳送 Cache-Control 和 Pragma 標頭。這些標頭會阻止 IE 上的下載!!!只使用 Expires 標頭,畢竟,它會要求下次再次下載檔案。這不是錯誤!IE 會將下載儲存在「Temporary Internet Files」資料夾中,直到下載完成。我知道這一點,因為我曾經下載一個大型檔案到「我的文件」,但「下載對話方塊」把它放在 Temp 資料夾中,並在最後才移動它。想想看。如果 IE 要求將檔案下載到 Temp 資料夾,設定 Cache-Control 和 Pragma 標頭會導致錯誤!

我希望這能為某人節省一些時間!
~Cody G.
Angelica Perduta
4 年前
我製作了一個腳本,使用 404 腳本調整大小並縮減原始影像,來產生用於網頁上的最佳化影像,但在某些伺服器上,它會產生影像,但由於某種 404 狀態的快取,導致無法使用它。我設法使用以下方法讓它運作,雖然我不太了解它,但我希望我的貼文能幫助其他有類似問題的人

header_remove();
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");
// ... 然後嘗試重新導向
// 201 = 請求已完成,導致建立了一個新的資源,但它仍然沒有載入
// 302 "暫時移動" 似乎可以載入它!
header("location:$dst", FALSE, 302); // 重新導向到我們現在擁有的檔案
To Top