FIFCOM实验室
FIFCOM实验室

PHP检测file_get_contents()返回的数据是否被压缩

PHP检测file_get_contents()返回的数据是否被压缩

最近折腾某天气 API 的时候踩到的坑(

正常情况下file_get_contents($api_url)会返回一个json字符串,接下来我使用json_decode()将其转换为数组来读取其内容。简单测试了一下,没有任何问题。但在实际使用时, json_decode() 偶尔会返回空数组。刚开始我以为是 file_get_contents()连接API服务器失败了,试着在浏览器打开 $api_url 却一切正常,迷惑….

var_dump()来检测是否真的没连接到API服务器,结果发现 file_get_contents()获取到的是一串乱码

https://blog.fifcom.cn/wp-content/uploads/2021/08/BGvZ4zQqjygOU3K7-1024x105.png
var_dump()

cmd里的curl试试,得到的是binary,应该就是上面那串乱码

https://blog.fifcom.cn/wp-content/uploads/2021/08/DPMKKtZQvxbUmmhJ-1024x92.png
curl in cmd

奇怪的是powershell里的curl一切正常

https://blog.fifcom.cn/wp-content/uploads/2021/08/qMrVFeJlmDztc7mb-1024x435.png
curl in powershell

将获取到的乱码保存至文件,用编辑器打开,发现文件开头(1f8b 0800)有些奇怪,像是文件签名

https://blog.fifcom.cn/wp-content/uploads/2021/08/MjwzCF08wIM3vXL6.png

查询得知, 1f8b08 是 gzip 的文件签名

https://blog.fifcom.cn/wp-content/uploads/2021/08/IchvTOxMYJxlRZgD-1024x194.png

原来数据是压缩过的。。。浏览器和powershell里的curl应该能自动识别数据是否被压缩并自动解压,但file_get_contents()就不支持了。。

由于此API不讲武德,没有说明哪些情况会压缩数据,所以可以写一个函数来检测数据是否被压缩并按需返回解压后的数据。

在被压缩的数据的响应头中会包含Content-Encoding: gzip,因此可以通过检测响应头来判断数据是否被压缩。如果数据被压缩则调用gzdecode()进行解压。file_get_contents()会将响应头储存在$http_response_header里,可以将$http_response_header转换为数组,方便判断。直接上代码

function url_get_contents(string $url): string
{
        $contents = file_get_contents($url);
        $header_arr = array();
        // 将响应头解析为数组
        foreach ($http_response_header as $value) {
            $t = explode(':', $value, 2);
            if (isset($t[1]))
                $header_arr[trim($t[0])] = trim($t[1]);
            else {
                $header_arr[] = $value;
                if (preg_match("#HTTP/[0-9]+\s+([0-9]+)#", $value, $out))
                    $header_arr['response_code'] = intval($out[1]);
            }
        }
        // 如果响应头中存在Content-Encoding且值为gzip,则表示数据被压缩
        if (isset($header_arr['Content-Encoding']) && $header_arr['Content-Encoding'] == "gzip") {
        // 返回解压后的数据
            return gzdecode($contents);
        } else {
            return $contents;
        }
}

完成!

赞赏
#
首页      笔记      PHP检测file_get_contents()返回的数据是否被压缩

FIFCOM

文章作者

更多文章

发表评论

textsms
account_circle
email

FIFCOM实验室

PHP检测file_get_contents()返回的数据是否被压缩
最近折腾某天气 API 的时候踩到的坑( 正常情况下file_get_contents($api_url)会返回一个json字符串,接下来我使用json_decode()将其转换为数组来读取其内容。简单测试了一下,没有任…
扫描二维码继续阅读
2021-08-14