近期的应项目需求,需要用到数据的导入与导出,因为数据比较多,思来想去使用了CSV格式的文件,结合了网上各位大佬的文章,具体代码如下:
在thinkphp/library/think下新建Csv.php文件:
<?php
namespace Think;
class Csv
{//导出csv文件public function put_csv($list,$title){$file_name = "exam".time().".csv";header('Content-Type: application/vnd.ms-excel');header('Content-Disposition: attachment;filename='.$file_name );header('Cache-Control: max-age=0');$file = fopen('php://output',"a");$limit = 1000;$calc = 0;foreach ($title as $v){$tit[] = iconv('UTF-8', 'GB2312//IGNORE',$v);}fputcsv($file,$tit);foreach ($list as $v){$calc++;if($limit == $calc){ob_flush();flush();$calc = 0;}foreach($v as $t){$tarr[] = iconv('UTF-8', 'GB2312//IGNORE',$t);}fputcsv($file,$tarr);unset($tarr);}unset($list);fclose($file);exit();}// csv导入 public function input_csv($csv_file) { $result_arr = array (); $i = 0; while($data_line = fgetcsv($csv_file,10000)) { //10000是表示可以处理多长的字符 if ($i == 0) { $GLOBALS ['csv_key_name_arr'] = $data_line; $i ++; continue; } foreach($GLOBALS['csv_key_name_arr'] as $csv_key_num => $csv_key_name ) { $result_arr[$i][$csv_key_name] = $data_line[$csv_key_num]; } $i++; } return $result_arr; }
}
?>
在控制器中调用:
<?php
namespace app\index\controller;
use think\Controller;
use think\Request;
use think\Db;
use think\Paginator;
use think\Validate;
use think\Csv; //此处是csv文件实现的关键
class Index extends Controller
{public function _initialize(){header("Content-type:text/html;charset=utf-8");} /** CSV试题导出*/public function downQuestions(){ $condition['qu_status'] = array('gt','-1');$csv = new Csv(); //实例化后才可以调用之前类文件定义好的方法$list = Db::table('gw_questions')->field('qu_name,qu_options,qu_answer,qu_describe,gw_topic.to_name,qu_time,te_name')->join('gw_topic','gw_topic.to_id=gw_questions.to_id')->join('gw_teacher','gw_teacher.te_id=gw_questions.te_id','LEFT')->where($condition)->select();$csv_title = array('题干内容','选项详情','参考答案','答案解析','题型','录入时间','录入人');$csv->put_csv($list,$csv_title);}/** CSV试题导入*/ public function upQuestionsWrite(){// 获取表单上传文件$file = request()->file('examfile');if(empty($file)) {$this->error('请选择上传文件');}// 移动到框架应用根目录/public/uploads/ 目录下$info = $file->move(ROOT_PATH.'public'.DS.'upload'); //获取文件(日期/文件),$info->getFilename();$filename = ROOT_PATH.'public'.DS.'upload/'.$info->getSaveName();$handle = fopen($filename,'r');$csv = new Csv(); $result = $csv->input_csv($handle); // 解析csv $len_result = count($result); if($len_result == 0){ $this->error('此文件中没有数据!');} $data_values = ''; for($i = 1;$i < $len_result+1;$i ++) { // 循环获取各字段值 $arr = array_values($result[$i]); $qu_name = iconv('gb2312','utf-8',$arr[0] ); // 中文转码 $qu_options = iconv('gb2312','utf-8',$arr[1]); $qu_answer = $arr[2]; $qu_describe = iconv('gb2312','utf-8',$arr[3]);$to_id = $arr[4]; $te_id = 1; //添加试题的教师 $data_values .= "('$qu_name','$qu_options','$qu_answer','$qu_describe','$to_id','$te_id'),"; } $data_values = substr($data_values,0,- 1 ); // 去掉最后一个逗号 fclose($handle); // 关闭指针// 批量插入数据表中$result = DB::execute("insert into gw_questions (qu_name,qu_options,qu_answer,qu_describe,to_id,te_id) values $data_values" );if($result){ $this->success('文件上传成功,数据已经导入!','exampaper',3);}else{// 上传失败获取错误信息$this->error($file->getError());}}
}
?>
模板页表单(此处我的项目中使用了框架,样式可以按自己的需求修改):
<form action="{:url('index/index/upQuestionsWrite')}" method="post" class="form form-horizontal" enctype="multipart/form-data" id="addform"> <div class="row cl"><label class="form-label col-xs-4 col-sm-2">选择试题文件:</label><div class="btn-upload form-group"><input type="text" name="uploadfile" id="uploadfile" class="input-text upload-url radius" readonly> <a href="javascript:void();" class="btn btn-primary radius"><i class="Hui-iconfont"></i>浏览文件</a><input type="file" name="examfile" class="input-file" multiple> </div> <a class="btn btn-success btn-submit">导入试题</a></div>
</form>
<script type="text/javascript">
$(function(){ //表单提交时判断是否有文件存在$(".btn-submit").click(function(){if($("input[name='uploadfile']").val() == ''){alert("请选择CSV文件!");return false;}else{$("#addform").submit();}});
});
</script>
注意: fgetcsv() 函数的用法,参考资料 https://www.runoob.com/php/func-filesystem-fgetcsv.html