Pragma不能单独起作用,因HTTP/1.1规范将其降级为向后兼容字段,仅当与Cache-Control共存时才被参考;PHP 8.3的cURL及内置HTTP客户端均遵循此规范。

直接设 Pragma: public 即可,但必须配合 Cache-Control 使用,单独设 Pragma 在现代 PHP+cURL 或浏览器中基本无效。
为什么 Pragma 不能单独起作用
HTTP/1.1 规范已明确将 Pragma 降级为向后兼容字段,仅在与 Cache-Control 共存时作为补充语义存在。PHP 8.3 的 cURL 或内置 HTTP 客户端(如 file_get_contents 配合 stream_context_create)均遵循该规范。若只设 Pragma: no-cache 而不设 Cache-Control,服务端或中间代理可能完全忽略它。
-
Pragma: no-cache不等于禁止缓存——它只对 HTTP/1.0 代理有意义,且不强制端到端刷新 - PHP 8.3 默认使用 HTTP/1.1,
Cache-Control才是真正生效的缓存控制指令 - 常见错误:在
curl_setopt($ch, CURLOPT_HTTPHEADER, [...])里只加'Pragma: no-cache',结果仍收到 304 响应或旧缓存内容
Pragma 和 Cache-Control 的正确配对方式
下载场景下目标是“每次请求都走新鲜响应”,不是“禁用所有缓存机制”。因此应优先用 Cache-Control 明确语义,Pragma 仅作兼容补全:
- 推荐组合:
'Cache-Control: no-cache, must-revalidate, max-age=0'+'Pragma: no-cache' - 若需彻底绕过缓存(如调试阶段),改用:
'Cache-Control: no-store'+'Pragma: no-cache'(no-store禁止任何存储,比no-cache更强) - 不要写
'Pragma: public'来“允许缓存”——下载文件通常不该被共享缓存,public可能导致 CDN 或代理缓存敏感内容
PHP 8.3 下载文件时的实际 header 设置示例
以 readfile() 方式提供服务器本地文件下载为例,响应头中 Pragma 的位置和写法:
立即学习“PHP免费学习笔记(深入)”;
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="data.csv"');
header('Content-Length: ' . filesize($file));
header('Cache-Control: no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache'); // ← 这行有效,但仅当上面 Cache-Control 存在时才被参考
header('Expires: 0');
注意:Pragma 必须出现在 Cache-Control 之后(顺序无关紧要),但逻辑上它只是冗余声明;真正起效的是 Cache-Control 的值。
容易被忽略的细节
PHP 8.3 对 header 输出更严格,以下情况会让 Pragma 彻底失效:
- 输出前已有任何字符(包括 BOM、空格、
echo ''),导致 header 发送失败,整个响应退化为普通 HTML 输出 - 启用了
output_buffering但未调用ob_end_clean(),缓冲区残留内容会污染 header - 在 CLI 模式下调用该脚本(无 HTTP 上下文),
header()函数直接静默失败,Pragma根本不会出现在响应中
真正决定下载行为是否“不缓存”的,从来不是 Pragma 这一行,而是 Cache-Control 的取值是否匹配你的意图,以及 header 是否成功发出。



















