前言
網上有很多介紹大量上傳資料的,感覺都是一個抄一個,這是自己寫的處理方式,在一些專案中已經應用.
主要利用 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萬條資料是很輕鬆.
本作品採用《CC 協議》,轉載必須註明作者和本文連結