如何通过PHP调用Carto SQL API实现GeoJSON文件下载?
问题解决方法
常见失败原因
- PHP配置项
allow_url_fopen未开启,导致file_get_contents无法请求远程HTTP资源 - 未设置合法的请求头(比如User-Agent),被Carto API拦截拒绝响应
- URL中SQL查询语句未做编码,特殊字符/空格导致请求路径解析错误
- HTTPS请求缺少SSL证书配置,请求验证失败
- 部分环境禁用
file_get_contents远程请求权限,需要改用cURL实现
解决方案
方案1:修复版file_get_contents实现(适合allow_url_fopen开启的环境)
先把SQL参数单独编码,再拼接URL,同时添加请求上下文配置:
<?php // 配置参数 $username = '替换为你的Carto用户名'; $tableName = 'ligonier_south_goshen1'; $fileName = 'ligonier_south_goshen1.geojson'; // 编码SQL语句避免特殊字符问题 $sql = urlencode("SELECT * FROM {$username}.{$tableName}"); $query = "https://{$username}.carto.com/api/v2/sql?format=GeoJSON&q={$sql}"; // 配置请求上下文 $context = stream_context_create([ 'http' => [ 'method' => 'GET', 'header' => 'User-Agent: PHP-Carto-Downloader/1.0', 'timeout' => 30 ], 'ssl' => [ // 调试阶段可临时关闭SSL验证,生产环境建议删除这两行配置正规CA证书 'verify_peer' => false, 'verify_peer_name' => false ] ]); // 请求数据 $result = file_get_contents($query, false, $context); if ($result === false) { echo "文件下载失败,请求API出错"; exit; } // 场景1:保存到服务器本地 if (file_put_contents($fileName, $result)) { echo "文件已成功保存到服务器"; } else { echo "文件保存失败,请检查目录写入权限"; } // 场景2:直接推送给浏览器下载(不需要存服务器的话用下面这段替换上面保存的代码) /* header('Content-Type: application/geo+json'); header('Content-Disposition: attachment; filename="' . $fileName . '"'); header('Content-Length: ' . strlen($result)); echo $result; exit; */ ?>
方案2:cURL实现(兼容性更高,推荐使用)
大部分生产环境都会开启cURL扩展,不受allow_url_fopen配置限制:
<?php $username = '替换为你的Carto用户名'; $tableName = 'ligonier_south_goshen1'; $fileName = 'ligonier_south_goshen1.geojson'; $sql = urlencode("SELECT * FROM {$username}.{$tableName}"); $query = "https://{$username}.carto.com/api/v2/sql?format=GeoJSON&q={$sql}"; $ch = curl_init($query); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_USERAGENT, 'PHP-Carto-Downloader/1.0'); curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 调试阶段临时关闭SSL验证,生产环境建议删除 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $result = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $error = curl_error($ch); curl_close($ch); if ($error || $httpCode != 200) { echo "请求失败,错误信息:{$error},HTTP状态码:{$httpCode}"; exit; } // 保存到服务器 if (file_put_contents($fileName, $result)) { echo "文件下载成功"; } else { echo "文件保存失败,请检查目录权限"; } ?>
额外排查提示
- 如果返回HTTP状态码为403,检查Carto账号的API权限,私有数据集需要在URL末尾拼接
&api_key=你的Carto API密钥 - 如果返回400,检查SQL语句语法是否正确,参数编码是否正常
- 保存文件失败的话,确认PHP运行用户对当前目录有写入权限
内容的提问来源于stack exchange,提问作者Hysteresis
相关产品推荐
相关产品推荐

