«

PHP file_get_contents获取https内容失败

时间:2026-10-9 07:34     作者:emer     分类: 无


前言

PHP用file_get_contents获取http内容没问题,换成https就报错了?这是最常见的问题,一般就是openssl扩展没开,或者SSL证书验证没过。本文讲怎么解决。

一、问题现象

<?php
$url = 'https://api.example.com/data';
$result = file_get_contents($url);

echo $result;

结果报错:

Warning: file_get_contents(): failed to open stream: Unable to find the wrapper "https"

或者:

Warning: file_get_contents(): SSL operation failed with code 1

二、常见原因

原因1:openssl扩展没装

PHP默认不开openssl扩展,file_get_contents不支持https。

原因2:allow_url_open没开

php.ini里禁了远程打开。

原因3:SSL证书验证失败

对方网站证书有问题,PHP验证不通过。

原因4:网络问题

服务器出不去,或者DNS解析不了。

三、排查步骤

第一步:看openssl扩展装了没

php -m | grep openssl

有输出就是装了,没输出就是没装。

或者写个phpinfo:

<?php
phpinfo();

搜"openssl",看有没有。

第二步:看allow_url_open开了没

<?php
echo ini_get('allow_url_fopen');

输出1就是开了,空就是没开。

第三步:用curl测试

curl https://api.example.com/data

curl能通就是PHP的问题,curl也不通就是网络问题。

四、解决方法

方法1:装openssl扩展(推荐)

CentOS

yum install php-openssl

或者:

yum install php7x-openssl

(x是你的PHP版本)

Ubuntu

apt install php-openssl

装完重启

systemctl restart php-fpm

方法2:改php.ini配置

打开php.ini,找到:

;extension=openssl

去掉前面的分号:

extension=openssl

然后重启php-fpm。

方法3:关掉SSL验证(临时)

不想改配置,可以在代码里关验证:

<?php
$context = stream_context_create([
    'ssl' => [
        'verify_peer' => false,
        'verify_peer_name' => false
    ]
]);

$result = file_get_contents('https://api.example.com/data', false, $context);

echo $result;

注意: 这是临时方案,生产环境建议把证书配好。

方法4:改用curl(推荐)

file_get_contents不好用,直接用curl:

<?php
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://api.example.com/data');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);

$result = curl_exec($ch);

if (curl_errno($ch)) {
    echo '错误: ' . curl_error($ch);
}

curl_close($ch);

echo $result;

curl比file_get_contents好用多了,推荐用curl。

五、常见坑

坑1:CLI和FPM配置不一样

命令行里openssl装了,网页上还是不行。

原因: CLI和FPM用不同的php.ini。

解决: 看phpinfo里的配置路径,改对应的那个。

坑2:装了扩展没重启

装完忘了重启php-fpm。

解决:

systemctl restart php-fpm

坑3:对方网站证书过期

对方网站SSL证书过期了,PHP验证不通过。

解决: 关验证,或者让对方更新证书。

坑4:allow_url_fopen没开

php.ini里禁了远程打开。

解决:

allow_url_fopen = On

坑5:防火墙挡了出站

服务器防火墙挡了443端口出站。

解决:

# 看能不能出去
curl -I https://www.baidu.com

# 不行的话开防火墙
firewall-cmd --add-port=443/tcp --permanent
firewall-cmd --reload

六、POST请求示例

file_get_contents发POST:

<?php
$url = 'https://api.example.com/submit';
$data = http_build_query([
    'name' => '张三',
    'age' => 20
]);

$context = stream_context_create([
    'http' => [
        'method' => 'POST',
        'header' => "Content-type: application/x-www-form-urlencoded\r\n",
        'content' => $data,
        'timeout' => 30
    ],
    'ssl' => [
        'verify_peer' => false,
        'verify_peer_name' => false
    ]
]);

$result = file_get_contents($url, false, $context);

echo $result;

还是建议用curl,更灵活。

七、封装函数

function http_get($url, $timeout = 30)
{
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);

    $result = curl_exec($ch);

    if (curl_errno($ch)) {
        $error = curl_error($ch);
        curl_close($ch);
        return ['code' => -1, 'msg' => $error];
    }

    curl_close($ch);
    return ['code' => 0, 'data' => $result];
}

// 使用
$res = http_get('https://api.example.com/data');
if ($res['code'] == 0) {
    echo $res['data'];
} else {
    echo '请求失败: ' . $res['msg'];
}

总结

记住:

  1. file_get_contents不支持https,是openssl扩展没装
  2. 装openssl扩展,重启php-fpm
  3. 或者关SSL验证临时解决
  4. 最推荐:改用curl,比file_get_contents好用多了

推荐方案:

直接用curl,别用file_get_contents搞https。

遇到问题加QQ23979811 协助处理

标签: PHP HTTPS SSL file_get_contents openssl