使用Curl下载JSON文件后json_decode返回空数组问题求助
问题:Curl下载150MB JSON文件后json_decode解析失败,直接读取网页文件却正常
我需要下载一个150MB的JSON文件,用Curl下载后调用json_decode返回空数组;但直接读取网页端的同一份文件时,解析完全正常。
之前遇到Invalid argument supplied for foreach()错误,把$data_apartments = json_decode($json_apartments,true);改成$data_apartments = (array)json_decode($json_apartments,true);也没用。添加JSON错误检测后,得到提示:Array - Syntax error, malformed JSON。
Curl下载代码
<?php $url = 'https://localhost.8888/apartments.json'; $destFile = 'aparts.json'; $fp = fopen($destFile, 'w+b'); if (false === $fp) { throw new RuntimeException ( 'fopen() failed. last error: ' . return_var_dump ( error_get_last () ) ); } $ch = curl_init(); if (false === $ch) { throw new RuntimeException ( 'curl_init() failed. last error: ' . return_var_dump ( error_get_last () ) ); } ecurl_setopt($ch, CURLOPT_URL,$url); ecurl_setopt($ch, CURLOPT_FILE, $fp); // write curl response to file ecurl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); ecurl_setopt($ch, CURLOPT_BINARYTRANSFER, true); ecurl_setopt($ch, CURLOPT_VERBOSE, true); ecurl_setopt($ch, CURLOPT_STDERR, $fp); ecurl_exec($ch); curl_close($ch); fclose($fp); function ecurl_setopt ( /*resource*/$ch , int $option , /*mixed*/ $value ):bool{ $ret=curl_setopt($ch,$option,$value); if($ret!==true){ //option should be obvious by stack trace throw new RuntimeException ( 'curl_setopt() failed. curl_errno: ' . return_var_dump ( curl_errno ($ch) ).'. curl_error: '.curl_error($ch) ); } return true; } function ecurl_exec ( /*resource*/$ch)/*:mixed depending on CURLOPT_RETURNTRANSFER*/{ $ret=curl_exec($ch); if($ret===false){ throw new RuntimeException ( 'curl_exec() failed. curl_errno: ' . return_var_dump ( curl_errno ($ch) ).'. curl_error: '.curl_error($ch) ); } return $ret; } function return_var_dump(){ $args = func_get_args (); ob_start (); call_user_func_array ( 'var_dump', $args ); return ob_get_clean (); } ?>
json_decode处理代码
<?php $json_apartments = file_get_contents('aparts.json'); $data_apartments = (array)json_decode($json_apartments,true); foreach($data_apartments as $jsons_apartments) { $_id = $json_apartments['_id']; $area_balconies_total = $json_apartments['area_balconies_total']; $area_given = $json_apartments['area_given']; } ?>
JSON文件示例
[ { "_id": "1cv", "area_balconies_total": 0, "area_given": 57.2 } ]
问题根源及解决办法
核心问题:JSON文件被Curl日志污染
你开启了CURLOPT_VERBOSE调试模式,并且把CURLOPT_STDERR指向了和下载文件同一个句柄$fp,导致Curl的调试日志(比如* Trying 127.0.0.1:8888...这类内容)直接写入到aparts.json中,破坏了原本的JSON结构,所以json_decode解析失败。修复步骤
- 分离日志和下载文件:单独创建日志文件句柄,把Curl错误输出指向该文件,不要和下载目标文件共用句柄:
// 新增日志文件句柄 $logFp = fopen('curl_download.log', 'w'); ecurl_setopt($ch, CURLOPT_STDERR, $logFp); // 执行Curl后关闭日志句柄 ecurl_exec($ch); fclose($logFp); - 删除废弃选项:
CURLOPT_BINARYTRANSFER在PHP 7.1及以上版本已废弃,无需设置,直接删除该行代码。 - 修复语法错误:原代码中
url = 'https://localhost.8888/apartments.json';缺少$符号,改为$url = 'https://localhost.8888/apartments.json';。
- 分离日志和下载文件:单独创建日志文件句柄,把Curl错误输出指向该文件,不要和下载目标文件共用句柄:
验证修复
重新下载后,打开aparts.json检查开头是否有Curl日志内容,若没有则说明文件正常。此时json_decode($json_apartments,true)会直接返回数组,无需强制转成数组,foreach循环也能正常执行。
内容的提问来源于stack exchange,提问作者Sergo
相关产品推荐
相关产品推荐

