php 8.1下载文件分两类:服务端拉取用curl流式写入(推荐大/中文件)或file_get_contents+file_put_contents(仅限小文件);客户端触发用readfile输出服务器文件,需前置安全校验与header设置。

PHP 8.1 下载文件到本地,核心是区分“服务端主动拉取”和“客户端触发下载”两类场景。前者适合后台任务(如定时抓取远程资源),后者用于用户点击后把服务器上的文件传给浏览器。方法选对了,内存、超时、大文件、安全性这些坑基本能避开。
服务端拉取:用 cURL 流式写入(推荐大/中文件)
cURL 是 PHP 8.1 中最稳定、可控性最强的远程文件获取方式,尤其适合下载几十 MB 以上的文件——它不全加载进内存,而是边读边写。
- 确保
curl扩展已启用(PHP 8.1 默认开启) - 设置超时、自动跳转、SSL 验证(如需)等关键选项
- 用
fopen()打开本地文件句柄,再通过CURLOPT_FILE直接写入,避免内存占用飙升
示例代码:
php$url = 'https://example.com/report.pdf';
$localPath = '/var/www/downloads/report_'.date('Ymd').'.pdf';
$ch = curl_init($url);
$fp = fopen($localPath, 'w');
if (!$fp) {
die('无法创建本地文件');
}
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 300); // 5分钟超时
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 生产环境建议设为 true 并配 CA
curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
fclose($fp);
if ($code !== 200) {
unlink($localPath);
die("下载失败,HTTP 状态码:$code");
}
echo "已保存至:$localPath";
?>
服务端拉取:file_get_contents + file_put_contents(仅限小文件)
适合几 MB 以内的配置文件、JSON、小图片等。代码最简,但会把整个文件内容一次性读进内存,大文件易触发 memory_limit 错误或超时。
- 务必检查
allow_url_fopen = On(PHP 8.1 默认开启,但某些托管环境会关闭) - 建议加异常捕获,防止 URL 不可达时脚本崩溃
示例代码:
$url = 'https://api.example.com/data.json';$localPath = '/tmp/fetched_data.json';
try {
$content = file_get_contents($url, false, stream_context_create([
'http' => ['timeout' => 30]
]));
if ($content === false) {
throw new Exception('获取内容失败');
}
file_put_contents($localPath, $content);
echo "小文件下载完成";
} catch (Exception $e) {
error_log($e->getMessage());
die('下载出错');
}
?>
客户端触发:readfile 输出(用户点链接下载服务器已有文件)
这不是“从网上下载”,而是让用户把存在你服务器磁盘上的文件(比如用户上传后生成的 PDF、导出的 Excel)安全地下载到本地。这是最常见的 Web 下载逻辑。
- 必须在任何输出前调用
header(),否则会报 “headers already sent” - 强烈建议校验文件路径,防止目录遍历(如
../../../etc/passwd) -
Content-Type尽量按真实 MIME 类型设置(可用mime_content_type()或finfo_file())
示例代码:
$filePath = '/var/www/uploads/invoice_123.pdf';// 安全校验:只允许特定目录下的文件,且不能含 ..
if (!is_file($filePath) || strpos(realpath($filePath), '/var/www/uploads/') !== 0) {
http_response_code(404);
exit('文件不存在或无权访问');
}
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="'.basename($filePath).'"');
header('Content-Length: '.filesize($filePath));
header('Cache-Control: no-cache');
readfile($filePath);
exit;
?>
补充:FTP 下载(适用于私有 FTP 服务器资源)
如果目标文件在你自己的 FTP 服务器上(非 HTTP),PHP 8.1 仍支持原生 FTP 函数,但需确认 extension=ftp 在 php.ini 中已启用。
- 用
ftp_connect()+ftp_login()建立连接 -
ftp_get()支持二进制模式,保障 ZIP/PDF 等文件不损坏 - 记得
ftp_close()释放连接
注意:FTP 明文传输不安全,生产环境建议改用 SFTP(需 ext-ssh2)或迁移到 HTTPS。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











