file_get_contents默认不跟随301重定向,需通过stream_context_create设置follow_location=true;更推荐用curl,配置curlopt_followlocation、curlopt_maxredirs等选项可稳定处理多级跳转及cookie、referer传递。

PHP用file_get_contents请求网址时遇301不自动跳转?
file_get_contents默认不跟随重定向,遇到301响应会直接返回状态码301的响应体(通常是HTML跳转页或空内容),而不是目标地址的内容。这不是bug,是设计如此——它只做“取内容”,不处理HTTP语义。
解决办法是改用stream_context_create配置follow_location和max_redirects:
$opts = [
'http' => [
'method' => 'GET',
'header' => "User-Agent: PHP\r\n",
'follow_location' => true,
'max_redirects' => 5,
'timeout' => 10,
]
];
$context = stream_context_create($opts);
$content = file_get_contents('https://example.com', false, $context);
注意:follow_location在PHP 5.2.10+才支持;若启用了open_basedir或allow_url_fopen=Off,该方式直接失效。
cURL比file_get_contents更可靠地处理301跳转
cURL是PHP中处理重定向最稳定的方式,它原生支持301/302自动跳转,且可控性更强:
立即学习“PHP免费学习笔记(深入)”;
-
CURLOPT_FOLLOWLOCATION设为true启用跳转 -
CURLOPT_MAXREDIRS限制跳转次数,防环形重定向 -
CURLOPT_RETURNTRANSFER确保返回内容而非直接输出 - 跳转过程中可监听
CURLOPT_HEADERFUNCTION观察每次跳转的Location头
示例:
$ch = curl_init('https://example.com');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 5,
CURLOPT_USERAGENT => 'PHP cURL',
CURLOPT_TIMEOUT => 10,
]);
$result = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); // 最终响应码(如200)
$final_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); // 实际到达的URL
curl_close($ch);
为什么get_headers看到301但file_get_contents拿不到跳转后内容?
get_headers只是读响应头,不触发重定向逻辑;而file_get_contents默认也不触发——两者行为完全独立。常见误操作是:先用get_headers确认301,再手动拼Location头里的URL去二次请求,这容易出错:
- Location值可能是相对路径(如
/new-page),需自己拼接协议和域名 - 跳转链可能多层(301 → 302 → 200),手动解析不可靠
- 某些服务对User-Agent或Referer有校验,两次请求头不一致导致失败
不如直接交给cURL或配置好context的file_get_contents,让底层HTTP栈统一处理。
跳转时Cookie和Referer怎么传递?
cURL默认不自动带Referer,也不跨跳转维持Cookie(除非显式设置):
- 用
CURLOPT_AUTOREFERER => true让cURL在跳转时自动设置Referer为上一个URL - 用
CURLOPT_COOKIEJAR和CURLOPT_COOKIEFILE配对实现跳转间Cookie透传(即使空文件也需指定路径) - 若目标站依赖Session,漏掉Cookie会导致跳转后登录态丢失、返回403或跳回登录页
例如:
curl_setopt($ch, CURLOPT_AUTOREFERER, true); curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookie.txt'); curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookie.txt');
临时文件路径要确保PHP有写权限;生产环境建议用sys_get_temp_dir()动态生成。
301跳转本身不难处理,难的是边界情况:跳转链深度、认证态延续、头字段校验、HTTPS混合跳转(如HTTP→HTTPS)。别图省事手动解析Location,用cURL并配全选项才是稳解。










