代码片段-处理50w行excel

需求分析:今天优化【通过excel上传手机号码,发送短信】需求。原本excel支持上传1000行手机号进行发送,由于实际线上客户需求远远大于1000个手机号,不得不分多次上传,经过优化,需要支持最大50w手机号(excel 50w行)发送,具体思路如下:

  • 1.读取远程execl文件,存入服务器tmp下;
  • 2.读取文件,拼接header&obj,每次处理5000条
  • 3.采用yield 每次吐出5000条数据,开启5个进程PRC请求网关,直到5w条全部处理完毕。
  • 经过测试环境验证,50w条数据处理花费大约5分钟左右,满足用户需求
<php?

#address set url
public function phraseFile($address = '')
    {
        $localTempFileName = '';
        if ($fp_remote = fopen($address, 'rb')) {
            $localTempFileName = tempnam('/tmp', 'assistant');
            if ($fp_local = fopen($localTempFileName, 'wb')) {
                while ($buffer = fread($fp_remote, 8192)) {
                    fwrite($fp_local, $buffer);
                }
                fclose($fp_local);
            }
            fclose($fp_remote);
        }

        if (!is_file($localTempFileName)){
            throw new Exception('文件打开失败');
        }
        $f = fopen($localTempFileName, 'r');
        if (!is_resource($f)){
            throw new Exception('文件打开失败');
        }
        $header = fgetcsv($f);//读取头部
        array_shift($header); //去除第一行mobile
        $mobileAndParams = [];
        $mobiles = [];
        while (!feof($f)){
            if (count($mobiles) >= self::ASSISTANTS_MAX_CUT_APART){
                $mobileAndParams = [];
                $mobiles = [];
            }
            $line = $oriLine = fgetcsv($f);
            $charset =  mb_detect_encoding(var_export($line,true),['UTF-8','ASCII','GBK','GB2312','BIG5','JIS','eucjp-win','sjis-win','EUC-JP'],true);
            $line = eval('return '.iconv($charset,'utf-8',var_export($line,true)).';');
            if (!$line){
                $this->errorLines[] = $oriLine;
                continue;
            }
            array_walk($line,function (&$item){
                $item = trim($item);
            });
            $mobile = trim(array_shift($line));
            $line = array_combine($header,$line);
            $param = json_encode($line);
            if (!$this->validateMobile($mobile)){
                $this->errorMobileList[] = $mobile;
                continue;
            }
            if (in_array($mobile,$mobiles)){
                continue;
            }
            $mobiles[] = $mobile;
            $mobileAndParams[$param][] = $mobile;
            if (count($mobiles) >= self::ASSISTANTS_MAX_CUT_APART){
                yield $mobileAndParams;
            }
        }
        if(count($mobiles) < self::ASSISTANTS_MAX_CUT_APART){
            yield $mobileAndParams;
        }
        fclose($f);

        // Delete temporary file
        unlink($localTempFileName);
    }

添加新评论