代码片段-处理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);
}