PHP如何从外部URL下载CSV文件并导入MySQL数据库
问题排查与解决方案
常见失败原因
- 身份校验缺失:浏览器能正常访问是因为本地缓存了登录态Cookie、接口鉴权Token,PHP脚本没有携带对应的校验参数,被服务端拦截返回了错误页面而非CSV内容
- 请求头校验不通过:多数服务端会校验User-Agent、Referer等请求头,PHP curl和fopen的默认请求头会被识别为爬虫直接拦截
- 302重定向未跟随:如果接口存在跳转逻辑,当前的curl配置没有开启自动跟随重定向,无法拿到最终的CSV文件
- SSL证书校验异常:虽然关闭了
CURLOPT_SSL_VERIFYPEER,但部分环境还需要关闭CURLOPT_SSL_VERIFYHOST才能正常请求HTTPS接口
修正后的完整实现代码
第一步:下载CSV内容的curl封装
function downloadCsv(string $url, array $headers = []): string|false { $ch = curl_init(); // 基础配置 curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 开启自动跟随重定向 curl_setopt($ch, CURLOPT_MAXREDIRS, 3); // 最多跟随3次跳转 curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 超时时间30秒 // 补充请求头,和浏览器请求头保持一致 $defaultHeaders = [ 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36', 'Accept: text/csv,application/csv,*/*;q=0.9', // 携带Cookie的格式:'Cookie: 从浏览器控制台网络面板复制的完整Cookie字符串' // Token鉴权的格式:'Authorization: Bearer 你的接口Token' ]; $headers = array_merge($defaultHeaders, $headers); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $data = curl_exec($ch); // 请求错误日志输出 if(curl_errno($ch)) { error_log('Curl请求错误:' . curl_error($ch)); curl_close($ch); return false; } $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); if($httpCode !== 200) { error_log('接口返回异常状态码:' . $httpCode . ',返回内容预览:' . substr($data, 0, 200)); curl_close($ch); return false; } curl_close($ch); return $data; }
第二步:解析CSV并插入MySQL
// 下载CSV $url = "https://data.xxx.com/api/export/替换为实际ID/date/csv?param=1¶m=2"; $csvContent = downloadCsv($url); if(!$csvContent) die('CSV下载失败'); // 写入临时文件解析 $tmpFile = tmpfile(); fwrite($tmpFile, $csvContent); rewind($tmpFile); // 连接MySQL,替换为实际数据库配置 $pdo = new PDO('mysql:host=数据库地址;dbname=库名;charset=utf8mb4', '用户名', '密码'); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 预处理插入SQL,替换为实际表名和字段 $insertSql = "INSERT INTO 目标表名 (字段1, 字段2, 字段3) VALUES (?, ?, ?)"; $stmt = $pdo->prepare($insertSql); // 跳过CSV表头,如CSV无表头可删除该行 fgetcsv($tmpFile); // 逐行插入数据库 while (($row = fgetcsv($tmpFile)) !== false) { // 此处可新增字段校验、格式转换逻辑 $stmt->execute([ $row[0], // 对应CSV第一列,和上面SQL字段顺序匹配 $row[1], $row[2] ]); } fclose($tmpFile); echo '数据插入完成,共插入' . $stmt->rowCount() . '条数据';
调试说明
- 优先打印curl返回的前200个字符,确认返回内容是CSV而非登录页、错误提示页
- 从浏览器F12控制台网络面板复制对应接口的完整请求头,替换到脚本的headers数组中,保证脚本请求和浏览器请求参数完全一致
- 若使用Cookie鉴权,直接复制浏览器请求中的完整Cookie内容到请求头即可
内容的提问来源于stack exchange,提问作者Fran Aguero
相关产品推荐
相关产品推荐

