推荐用 curl 下载,因其支持重定向、超时、http 头定制且内存占用低;小文件可用 file_get_contents + file_put_contents;需认证时用 stream_context_create;注意二进制模式写入、超时设置及权限问题。

PHP 7.4 把文件从远程服务器下载到本地,核心是“读取远程资源 + 写入本地磁盘”。方法选择取决于文件大小、网络稳定性、是否需要进度控制或认证等。下面列出最常用、最稳妥的几种方式,并说明常见问题和应对建议。
推荐用 cURL 下载(适合大多数场景)
cURL 是 PHP 7.4 默认启用的扩展(需确认 extension=curl 在 php.ini 中未被注释),支持重定向、超时、HTTP 头定制、断点续传基础能力,且内存占用低,不把整个文件加载进内存。
示例代码:
$url = 'https://example.com/report.pdf';
$localPath = '/var/www/downloads/report_' . date('YmdHis') . '.pdf';
$ch = curl_init($url);
$fp = fopen($localPath, 'wb');
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_exec($ch);
if (curl_errno($ch)) {
error_log('cURL error: ' . curl_error($ch));
}
curl_close($ch);
fclose($fp);
// 检查是否写入成功
if (filesize($localPath) === 0) {
unlink($localPath);
throw new Exception('下载失败:文件为空');
}
关键点:
- 务必用
fopen(..., 'wb')以二进制模式打开,避免 Windows 下换行符损坏图片/PDF 等二进制文件 - 设置
CURLOPT_TIMEOUT防止大文件卡死 - 下载后检查
filesize()或用curl_getinfo($ch, CURLINFO_HTTP_CODE)判断 HTTP 状态码是否为 200
小文件可用 file_get_contents + file_put_contents(简单但有风险)
适合几 MB 以内的文本、JSON、小图等。优点是代码极简;缺点是整块加载进内存,大文件易触发 memory_limit 错误,且无错误细节反馈。
$url = 'https://api.example.com/data.json';
$content = file_get_contents($url);
if ($content === false) {
throw new Exception('file_get_contents failed for: ' . $url);
}
file_put_contents('/tmp/data.json', $content);
注意事项:
- 确保
allow_url_fopen = On(PHP 7.4 默认开启,但部分主机禁用) - 若远程地址返回 404/500,
file_get_contents仍可能返回false,但不会抛异常,必须手动判断 - 不适用于需要 Basic Auth、Cookie 或自定义 Header 的请求(除非配合
stream_context_create)
带身份验证或复杂请求头?用 stream_context_create
当目标 URL 需要 Bearer Token、API Key 或 Basic Auth 时,file_get_contents 配合上下文更轻量,比 cURL 更简洁。
$url = 'https://private-api.com/file.zip';
$options = [
'http' => [
'method' => 'GET',
'header' => "Authorization: Bearer abc123\r\n" .
"User-Agent: PHP-7.4\r\n"
]
];
$context = stream_context_create($options);
$content = file_get_contents($url, false, $context);
if ($content === false) {
throw new Exception('Auth failed or network error');
}
file_put_contents('/tmp/private.zip', $content);
适用场景:
- 需要简单 Header(如 Authorization、Referer)
- 不想引入 cURL 的初始化/关闭流程
- 注意:不支持自动重定向(
follow_location需手动设,且 PHP 7.4 对其支持有限)
常见问题与解决建议
1. 下载的文件打不开 / 内容损坏
大概率是没用 'wb' 模式写入,尤其在 Windows 上。改用 fopen($path, 'wb'),并确认源文件是真实可访问的(浏览器直接打开 URL 测试)。
2. 提示 “failed to open stream: Unable to find the wrapper”
说明 allow_url_fopen 被关闭。检查 php.ini 中该配置项,或改用 cURL(它不依赖此设置)。
3. 下载中途断开 / 超时
cURL 加 CURLOPT_TIMEOUT 和 CURLOPT_CONNECTTIMEOUT;对超大文件,考虑分块下载或加重试逻辑(如 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true) + 循环读取)。
4. 权限被拒绝(Permission denied)
确保 PHP 进程(如 www-data、nginx 用户)对目标目录有写权限:chown -R www-data:www-data /var/www/downloads,并确认目录存在。
5. 中文文件名乱码或无法保存
PHP 本身不处理 HTTP 响应头中的 Content-Disposition。如需按服务端指定的原始文件名保存,需先用 cURL 获取 header,再解析 filename*= 或 filename= 字段,再做 UTF-8 转义。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











