PHP 8.2 中“下载”分浏览器端下载和服务端下载两类:前者用 header + readfile 实现用户保存服务器文件;后者用 file_get_contents + file_put_contents 或 cURL 将远程文件拉取至本地服务器。

PHP 8.2 把文件“下载到本地”,其实分两种场景:一种是让访问网页的用户把服务器上的文件保存到自己电脑(即浏览器端下载);另一种是让 PHP 脚本主动从远程 URL 把文件拉取并存到你自己的服务器硬盘上(即服务端下载)。新手常混淆这两者,下面分开讲清楚,直接可用、不绕弯。
让用户把服务器文件下载到自己电脑
这是最常见的需求,比如用户点击“下载合同PDF”。关键不是“传文件”,而是用 HTTP 头告诉浏览器:“这不是网页,是附件,请弹窗保存”。PHP 8.2 完全兼容以下写法:
- 先检查文件是否存在且可读:
file_exists($path) && is_readable($path) - 用
basename($path)提取真实文件名,避免路径注入(安全必须) - 设置三组关键 header:
header('Content-Type: application/octet-stream');header('Content-Disposition: attachment; filename="' . $safeName . '");header('Content-Length: ' . filesize($path)); - 清空输出缓冲(防意外空格或警告干扰下载):
ob_end_clean(); - 最后用
readfile($path)流式输出,不占内存,适合大文件
让 PHP 自己从网上拉文件存到服务器
比如定时抓取一张图片存到 /uploads/ 目录。PHP 8.2 推荐用 file_get_contents() + file_put_contents(),简洁可靠:
- 一行就能下小文件:
file_put_contents('/var/www/html/img.jpg', file_get_contents('https://example.com/photo.jpg')); - 注意:确保目标目录有写权限,且
allow_url_fopen = On(PHP 配置默认开启) - 若要下大文件或需要超时、重试、自定义 User-Agent,改用 cURL:
初始化curl_init(),设CURLOPT_RETURNTRANSFER => true,执行后写入本地 - 不推荐用
copy()——它不报错细节,调试困难
新手最容易踩的坑
不是代码写不对,而是环境和逻辑没理清:
立即学习“PHP免费学习笔记(深入)”;
- 别在下载脚本里 echo 或 var_dump:任何额外输出都会破坏 header,导致“无法下载”或文件损坏
-
路径别写相对路径如 './files/a.pdf':用
__DIR__ . '/files/a.pdf'或realpath()确保绝对路径 -
中文文件名要处理:浏览器兼容性差,建议用英文名,或用
rawurlencode()编码:filename*=UTF-8''%E6%8A%A5%E5%91%8A.pdf -
大文件记得关超时:加
set_time_limit(0),否则脚本中途被杀
搞懂这两类“下载”的本质区别,再套用上面任一模板,就能稳稳跑通。不需要框架,原生 PHP 8.2 就够用。



















