file_get_contents远程请求需用stream_context_create传header,因第二参数非选项数组而是布尔值;返回false常因HTTP错误码而非网络问题,应检查$http_response_header或改用cURL。

file_get_contents 远程 URL 时怎么带自定义 Header
直接传数组给 file_get_contents 不生效,必须用 stream_context_create 构造上下文。PHP 默认的 HTTP 流不支持在函数参数里塞 header,这是最常见的误解来源。
典型错误写法:
file_get_contents('https://api.example.com/data', ['header' => "Authorization: Bearer xyz"])——这会报 Warning:file_get_contents() expects parameter 2 to be int, array given,因为第二个参数是 $use_include_path(布尔值),不是选项数组。
- 正确方式是把 header 放进
http选项里,再用stream_context_create包一层 - header 必须是字符串,每行以
\r\n结尾(Windows 风格换行),不能用\n - 如果服务端校验
User-Agent,不加可能返回 403;部分 API 强制要求Accept: application/json
$opts = [
'http' => [
'method' => 'GET',
'header' => "Authorization: Bearer abc123\r\n" .
"User-Agent: PHP-Script/1.0\r\n" .
"Accept: application/json\r\n",
'timeout' => 10,
]
];
$context = stream_context_create($opts);
$result = file_get_contents('https://api.example.com/v1/user', false, $context);
为什么 file_get_contents 有时返回 false,但没报错
默认情况下,PHP 遇到 HTTP 错误状态码(如 401、404、500)仍会返回 false,且不抛异常,只触发 warning(如果 error_reporting 开启了 E_WARNING)。你看到空结果或 false,大概率是服务端拒绝了请求,而不是网络不通。
- 检查是否启用了
allow_url_fopen(phpinfo()查看,禁用时直接 fatal error) - 用
error_get_last()紧跟在file_get_contents后获取最后错误信息 - 更可靠的方式:配合
$http_response_header全局变量,它会在成功请求后自动填充响应头
$result = file_get_contents('https://httpbin.org/status/404');
if ($result === false) {
$err = error_get_last();
echo "Error: " . ($err['message'] ?? 'Unknown');
// 检查响应头
if (isset($http_response_header)) {
foreach ($http_response_header as $line) {
if (strpos($line, 'HTTP/') === 0) {
echo "Status: " . $line;
break;
}
}
}
}
替代方案:cURL 比 file_get_contents 更可控
当需要处理重定向、证书验证、POST body、cookie、或调试 header 交互时,curl_exec 是更稳妥的选择。特别是访问 HTTPS 站点时,file_get_contents 容易因 SSL 上下文缺失而失败(比如证书过期、不匹配),而 cURL 可显式控制 CURLOPT_SSL_VERIFYPEER 和 CURLOPT_CAINFO。
立即学习“PHP免费学习笔记(深入)”;
-
file_get_contents无法设置 POST 数据体,除非改method和content选项,但不如 cURL 直观 - cURL 支持
CURLOPT_HEADER直接拿到响应头,无需依赖全局变量 - 某些共享主机禁用
allow_url_fopen,但允许 cURL(更常见)
$ch = curl_init('https://httpbin.org/get');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer test',
'Accept: application/json'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
安全与生产环境注意事项
远程文件访问本质是发起外部 HTTP 请求,容易成为 SSRF(服务器端请求伪造)入口。如果你的 URL 来自用户输入(比如表单、API 参数),绝不能直接拼接进 file_get_contents 或 cURL。
- 禁止未经校验地使用
$_GET['url']、$_POST['target']等动态值 - 白名单域名 + 协议限制(只允许
https://,拒绝file://、php://filter等伪协议) - 超时必须设(
timeout/CURLOPT_TIMEOUT),否则一个挂掉的第三方接口可能拖垮整个 PHP-FPM worker - PHP 8.1+ 中,
file_get_contents对非 HTTP(S) 协议默认禁用,但旧版本仍需手动过滤
最常被忽略的一点:即使你只访问自己信任的 API,也要注意响应体大小。不设 max_redirects 或不限制响应长度,可能被恶意响应耗尽内存。











