前言
网上有很多介绍大量上传数据的,感觉都是一个抄一个,这是自己写的处理方式,在一些项目中已经应用.
主要利用 yield 完成文件读取,这个重点看会了,其他基本就很简单.
代码部分
一.controller写法
//获取请求的参数 | |
$arrayParams = Request::all(); | |
$objCsvFile = $arrayParams['csv_file']; | |
$strRealPath = $objCsvFile->getRealPath();//tmp路径, 这里可以先保存到自己预定路径,再进行读取 | |
//**************重点在这一步********************// | |
$glob = CommonUtilFunction::readPathCsvFile($strRealPath); | |
//********************************************// | |
$intRowNum = 0; | |
while($glob->valid()) { | |
$arrayNewLineData = []; | |
$intRowNum++; | |
if (1 === $intRowNum) { | |
//第一行跳过,一般是标题 | |
$glob->next(); | |
continue; | |
} | |
$arrayLineData = $glob->current(); | |
//处理空字符串 空行 | |
/** | |
* 一般csv有两种行数据可以被认为是空行 | |
* 第一种 ',,,,,,,,,,,,,,,,,,,,,,,,,,',类似这种纯逗号没有任何数据 | |
* 第二种 ' ',是真的空行,什么也没有 | |
* 处理完成返回一个统一的数组 [] | |
*/ | |
$arrayLineData = CommonUtilFunction::dealCsvLineData($arrayLineData);//跳过空行if (true === empty($arrayLineData)) {$glob->next();continue;} | |
//自己的代码逻辑... | |
// 避免意外错误unset($arrayNewLineData);$glob->next(); | |
// 处理下一行数据 | |
} |
二.yield读取数据以及处理空行方法
/** | |
* @description 迭代器读取csv文件 | |
* @param $strCsvPath | |
* @return \Generator | |
*/ | |
public static function readPathCsvFile($strCsvPath) | |
{ | |
if ($handle = fopen($strCsvPath, 'r')) { | |
while (!feof($handle)) { | |
yield fgetcsv($handle); | |
} | |
fclose($handle); | |
} | |
} | |
/** | |
* @description 处理c单行信息 | |
* @param $arrData | |
* @return \Generator | |
*/ | |
public static function dealCsvLineData($arrData = []) | |
{ | |
$arrAfterData = []; | |
if (false === empty($arrData)) { | |
//去除每个字符串 前后空格foreach ($arrData as &$colData) { | |
//检测对应编码格式 csv文件格式Shift-JIS$strEncodeType = mb_detect_encoding($colData, ['UTF-8', 'Shift-JIS']); | |
//如果认为utf-8格式不用转码, shift-jis格式需要转为utf8格式 | |
if ('SJIS' === $strEncodeType) { | |
//jis=>utf8 | |
$colData = mb_convert_encoding($colData, 'UTF-8', 'Shift-JIS'); | |
} | |
$colData = trim($colData);} | |
//去除空行 | |
$isEmptyRow = true; | |
foreach ($arrData as $item) { | |
if ('' !== $item) { | |
$isEmptyRow = false; | |
break; | |
} | |
} | |
if (false === $isEmptyRow) { | |
$arrAfterData = $arrData; | |
} | |
} | |
return $arrAfterData; | |
} |
结论
使用yield可以很大程度上减低服务器开销,压力在数据库方面.上限没有测试过,不过1万条数据是很轻松.