thinkphp5匯入匯出大量csv資料
阿新 • • 發佈:2018-11-08
在thinkphp/library/think下新建Csv.php檔案:
<?php /** * Created by PhpStorm. * User: sunin * Date: 2018/10/18 * Time: 17:42 */ namespace think; class Csv { //匯出csv檔案 public function put_csv(&$data, $titleList = array(), $fileName = '') { ini_set("max_execution_time", "3600"); $csvData = ''; // 標題 $nums = count($titleList); for ($i = 0; $i < $nums - 1; $i++) { $csvData .= '"' . $titleList[$i] . '",'; } $csvData .= '"' . $titleList[$nums - 1] . "\"\r\n"; foreach ($data as $key => $row) { $i = 0; foreach ($row as $_key => $_val) { $_val = str_replace("\"", "\"\"", $_val); if ($i < ($nums - 1)) { $csvData .= '"' . $_val . '",'; } elseif ($i == ($nums - 1)) { $csvData .= '"' . $_val . "\"\r\n"; } $i++; } unset($data[$key]); } $csvData = mb_convert_encoding($csvData, "cp936", "UTF-8"); $fileName = empty($fileName) ? date('Y-m-d-H-i-s', time()) : $fileName; $fileName = $fileName . '.csv'; header("Content-type:text/csv;"); header("Content-Disposition:attachment;filename=" . $fileName); header('Cache-Control:must-revalidate,post-check=0,pre-check=0'); header('Expires:0'); header('Pragma:public'); echo $csvData; exit(); } // csv匯入,支援10W+資料 public function input_csv($filename,$field,$table) { //$field 打散為陣列 $fieldArr = explode(',', $field); //CSV轉陣列 $excelData $content = trim(file_get_contents($filename)); $excelData = explode("\n",$content); //把字串打散為陣列 //刪除第一行標題 array_splice($excelData, 0, 1); // 將這個大量資料(10W+)的陣列分割成5000一個的小陣列。這樣就一次批量插入5000條資料。mysql 是支援的。 $chunkData = array_chunk($excelData ,5000); $count = count($chunkData); for ($i = 0; $i < $count; $i++) { $insertRows = array(); foreach($chunkData[$i] as $value){ //轉碼,有中文不要用這種方式,會出亂碼 //$string = mb_convert_encoding(trim(strip_tags($value)), 'utf-8', 'gbk'); $string = trim(strip_tags($value));//轉碼 $v = explode(',', $string); //把字串打散為陣列 $row = array(); for($j=0;$j<count($fieldArr);$j++){ $row[$fieldArr[$j]] = $v[$j]; } $sqlString = "('".implode( "','", $row )."')"; //把陣列元素組合為字串 批量 $insertRows[] = $sqlString; } $result = $this->addData($table,$insertRows,$field); //批量將sql插入資料庫。 } return $result; } public function addData($table,$rows,$field) { if(empty($rows)){ return false; } //資料量較大,採取批量插入 $data = implode(',', $rows); $sql = "INSERT IGNORE INTO $table ($field) VALUES {$data}"; $result = Db::execute($sql); return $result; } }
對應的控制器
use think\Db; use think\Request; use think\Csv; //接受上傳的檔案儲存並匯入資料庫 public function addStory() { //表名 $table = 'tablename'; //清空表中資料,自己權衡是否使用 //$sql = "TRUNCATE TABLE $table"; //Db::execute($sql); //資料庫中欄位名 $field = 'id,name,bust,bust_position,dialogue'; //上傳的CSV檔案 $files = Request::instance()->file("file"); $info = $files->move(ROOT_PATH . 'public' . DS . 'uploads'); $filename = ROOT_PATH.'public'.DS.'uploads/'.$info->getSaveName(); $csv = new Csv(); $result = $csv->input_csv($filename,$field,$table); return $result; } //接受表名並匯出表格 public function putStory() { //匯出csv表格 $csv = new Csv(); //使用原生寫法,thinkPHP查詢方法會有額外資料,導致匯出失敗 $table = 'tablename'; $sql = "select * from $table"; $data = Db::query($sql); $titleList = array('id','是否為起始劇情','劇情組名','劇情組簡介','對話方塊資源','對話方塊位置','該劇情組屬於哪一情景'); $csv->put_csv($data, $titleList); }