php怎么下载文件_强制浏览器下载文件的header设置【说明】

19次阅读

强制浏览器下载文件需严格设置三个 header:关闭缓存、Content-Type 为 application/octet-stream、Content-Disposition 指定 rawurlencode 编码的附件名,且须在任何输出前调用并避免 bom、空格、session 启动等干扰。

php怎么下载文件_强制浏览器下载文件的header设置【说明】

php 中用 header 强制浏览器下载文件的关键设置

直接生效的核心是三组 header:关闭缓存、声明内容类型为 application/octet-stream、用 Content-Disposition 指定附件名。漏掉任意一个,都可能导致文件被打开而非下载,或在某些浏览器(如 chrome 119+)中静默失败。

必须设置的三个 header 及其顺序和参数细节

顺序不能颠倒,且需在任何输出(包括空格、BOM、echo)之前调用:

header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="' . rawurlencode($filename) . '"');

其中:

  • Cache-Control 避免代理或浏览器缓存旧响应,no-storeno-cache 更严格,推荐同时使用
  • Content-Type 必须是无关联类型的二进制流,application/octet-stream 最稳妥;不要用 text/plain 或推测 MIME 类型,否则 safari 可能直接渲染
  • filename 值必须用 rawurlencode() 编码(不是 urlencode()),否则中文名在 firefoxedge 中会乱码;双引号不可省略

下载前必须检查的常见错误点

这些错误不会报 PHP 错误,但会导致 header 失效:

  • 脚本开头存在 UTF-8 BOM(尤其 windows 编辑器保存时默认添加),用 hexdump -C your.php | head 检查前几字节是否为 ef bb bf
  • header() 前有 echovar_dump()、甚至换行或空格
  • 启用了 output_buffering 但未显式 ob_end_clean(),导致缓冲区已有内容
  • 使用了 session_start()session 文件已写入,此时 PHP 自动发送 Set-cookie,破坏 header 流程

完整可运行的最小示例(含安全处理)

以下代码假设文件路径已校验,不接受用户直传路径:

$file_path = '/var/www/files/report.pdf'; $filename = '2024年度报告.pdf';  if (!is_file($file_path) || !is_readable($file_path)) {     http_response_code(404);     exit; }  ob_end_clean(); header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); header('Content-Type: application/octet-stream'); header('Content-Length: ' . filesize($file_path)); header('Content-Disposition: attachment; filename="' . rawurlencode($filename) . '"');  readfile($file_path); exit;

注意:Content-Length 虽非强制,但加上后能避免 Chrome 下载进度条卡在 99%,也方便断点续传支持。

text=ZqhQzanResources