You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP fgetcsv读取大CSV遇SSL连接重置错误排查求助

问题描述

使用PHP的fgetcsv脚本加载包含115000行的CSV文件并更新数据库,但读取到约111000行时停止,报错:

Warning: fgetcsv(): SSL: Connection reset by peer in "script folder".

每次均在4.8632356325785秒后停止,已调整php.ini中的执行时长、内存限制等参数仍无法解决,错误指向代码行:

while (($data_string = fgetcsv($handle, ";")) !== FALSE) {

相关核心代码如下:

$row = 1;

$url = $_POST['url_file'];
$handle = fopen($url,"r");

$done = 0;

while (($data_string = fgetcsv($handle, ";")) !== FALSE) {

    $num = count($data_string);
    $row++;
    $ean13 = "";
    $price = "";
    $quantity = "";
    $data = explode(";",$data_string[0]);
    echo ob_get_clean();
问题原因及解决方案

核心原因

这个错误是远程服务器主动断开了SSL连接,和PHP的执行时间、内存限制无关——报错明确指向SSL层面的连接重置,且每次触发时间固定,说明是远程端设置了连接超时阈值(比如5秒内的连接时长或数据传输量限制),当脚本持续读取超过该阈值后,对方服务器强制断开连接。

同时你的代码存在两个加剧问题的细节:

  1. fgetcsv参数使用错误:第二个参数应为每行最大字节数,你传入了分隔符";",导致fgetcsv无法正确解析行,反而把分隔符当成字节数限制,引发读取不完整,拖慢读取速度,更容易触发远程超时。
  2. 循环内频繁调用echo ob_get_clean():强制清空输出缓冲区并输出的操作会增加IO开销,拉长单循环耗时,更快达到远程服务器的超时限制。

解决步骤

  1. 修复fgetcsv参数错误
    正确用法是将分隔符放在第三个参数,第二个参数传0表示不限制行长度:

    while (($data_string = fgetcsv($handle, 0, ";")) !== FALSE) {
    

    修正后能让fgetcsv正常解析行,提升读取效率。

  2. 先下载CSV到本地再处理
    直接读取远程URL易受网络波动、服务器限制影响,建议先将文件下载到本地:

    $url = $_POST['url_file'];
    $localPath = './temp_csv_file.csv';
    // 用curl下载更稳定,支持超时设置
    $ch = curl_init($url);
    $fp = fopen($localPath, 'w');
    curl_setopt($ch, CURLOPT_FILE, $fp);
    curl_setopt($ch, CURLOPT_TIMEOUT, 300); // 设置下载超时为5分钟
    curl_exec($ch);
    curl_close($ch);
    fclose($fp);
    
    // 读取本地文件
    $handle = fopen($localPath, "r");
    

    本地读取完全规避远程连接超时问题,效率也更高。

  3. 优化循环内的IO与冗余操作

    • 去掉循环内的echo ob_get_clean(),如需输出进度,可每处理N行(如1000行)输出一次,减少IO次数;
    • 移除多余的explode(";",$data_string[0])——fgetcsv已经按;将行拆分为数组,直接使用$data_string即可。

    优化后的循环示例:

    $row = 1;
    while (($data_string = fgetcsv($handle, 0, ";")) !== FALSE) {
        $row++;
        $ean13 = "";
        $price = "";
        $quantity = "";
        $data = $data_string; // 直接使用fgetcsv解析后的数组
        // 每1000行输出一次进度
        if ($row % 1000 == 0) {
            echo "已处理{$row}行\n";
            ob_flush();
            flush();
        }
    }
    
  4. 若必须远程读取,优化连接稳定性
    可通过添加HTTP头保持连接,或临时关闭SSL证书验证(仅在证书有问题时使用):

    $opts = [
        'http' => [
            'header' => "Connection: keep-alive\r\n"
        ],
        'ssl' => [
            'verify_peer' => false,
            'verify_peer_name' => false
        ]
    ];
    $context = stream_context_create($opts);
    $handle = fopen($url, "r", false, $context);
    

内容的提问来源于stack exchange,提问作者PicenoComputers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 20:12:46