项目开发中,很多时候要将外部CSV文件导入到数据库中或者将数据导出为CSV文件,那么具体该如何实现呢?本文将使用PHP并结合mysql,实现了CSV格式数据的导入和导出功能。
常用函数:
fopen() 函数打开文件或者 URL fgetcsv() 函数从文件指针中读入一行并解析 CSV 字段。 与 fgets() 类似,不同的是 fgetcsv() 解析读入的行并找出 CSV 格式的字段,然后返回一个包含这些字段的数组。 fgetcsv() 出错时返回 FALSE,包括碰到文件结束时。 fputcsv() 函数将行格式化为 CSV 并写入一个打开的文件。 该函数返回写入字符串的长度。若出错,则返回 false。。 mb_convert_encoding ( string $str , string $to_encoding [, mixed $from_encoding = mb_internal_encoding() ]) 转换字符的编码 iconv ( string $in_charset , string $out_charset , string $str ) 函数返回字符串
我们先准备mysql数据表,假设项目中有一张记录学生信息的表student,并有id,name,sex,age分别记录学生的姓名、性别、年龄等信息。
DROP TABLE IF EXISTS `ks_student`; CREATE TABLE `ks_student` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(32) DEFAULT NULL, `sex` char(2) DEFAULT NULL, `age` tinyint(3) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
我们还需要一个html交互页面,放置导入表单和导出按钮。
<form id="uploadForm" action="__URL__/action?act=import" method="post" enctype="multipart/form-data"> <input type="text" name="username" class="username"> <br/> <p>请选择要导入的CSV文件:<br/> <input type="file" name="file" class="file"> <input type="hidden" name="act" class="act" value="import"> <input type="submit" class="btn import" value="导入CSV"> </form> <a href="__URL__/action?act=export"> <button type="submit" class="btn btn-default record">导出CSV</button> </a> <div class="content" style="width:300px;height:auto;"></div> <script> $(function(){ $('#uploadForm').ajaxForm({ dataType: 'json', success: processJson }); function processJson(re){ if(re.status == '1'){ var re = re.info; for(var i=0; i < re.length;i++){ var html=""; html +="<div>"; html +='<span class="name" style="padding-right: 30px;">'+re[i].name+'</span>'; html +='<span class="sex" style="padding-right: 30px;">'+re[i].sex+'</span>'; html +='<span class="age">'+re[i].age+'</span>'; html +="</div>"; $(html).appendTo(".content"); } } else{ alert(re.info); } } $(".export").click(function(){ var url ="__URL__/action?act=export"; window.location.href=url; }); }); </script>
选择好本地csv文件后,点击导入,提交到do.php?action=import处理,而点击导出按钮则请求地址do.php?action=export进行数据导出处理。
使用tp3.2框架具体处理
1.配置数据库
return array( //'配置项'=>'配置值' /* 数据库设置 */ 'DB_TYPE' => 'mysql', // 数据库类型 'DB_HOST' => 'localhost', // 服务器地址 'DB_NAME' => 'user', // 数据库名 'DB_USER' => 'root', // 用户名 'DB_PWD' => '', // 密码 'DB_PORT' => 3306, // 端口 'DB_PREFIX' => 'ks_', // 数据库表前缀 'DB_CHARSET'=> 'utf8', // 字符集 'DB_DEBUG' => TRUE, // 数据库调试模式 开启后可以记录SQL日志 3.2.3新增 'SHOW_PAGE_TRACE' =>true, // 显示页面Trace信息 );
2.根据get过来的参数,分别处理导入和导出过程,php结构如下:
$action = $_GET['action']; if ($action == 'import') { //导入CSV //导入处理 } elseif ($action=='export') { //导出CSV //导出处理 }
注意php自带的fgetcsv函数可以轻松处理csv,使用该函数可以从文件指针中读入一行并解析CSV字段。下面的函数将csv文件字段解析并以数组的形式返回。
function input_csv($handle) { $out = array (); $n = 0; while ($data = fgetcsv($handle, 10000)) { $num = count($data); for ($i = 0; $i < $num; $i++) { $out[$n][$i] = $data[$i]; } $n++; } return $out; }
导入CSV处理流程:校验csv文件合法性(本文忽略)->打开读入并解析csv文件中的字段->循环获取各字段值->批量添加到数据表中->完成。
导出CSV处理流程:读取学生信息表->循环记录构建逗号分隔的字段信息->设置header信息->导出文件(下载)到本地。
<?php namespace Home\Controller; use Think\Controller; class IndexController extends Controller { public function index(){ $this->display(); } /* csv文件是由逗号分割符组成的纯文本文件,你可以用excel打开,效果跟xls表个一样。 导出CSV处理流程:读取学生信息表->循环记录构建逗号分隔的字段信息->设置header信息->导出文件(下载)到本地 */ //导入导出csv public function action(){ header('Content-type:text/html;charset=utf8'); $action = I("act"); if ($action == 'import'){ //导入CSV $username = I("username"); $filename = $_FILES['file']['tmp_name']; if(empty($filename)){ echo '请选择要导入的CSV文件!'; exit; } $handle = fopen($filename, 'r'); $result = $this->input_csv($handle); //解析csv $len_result = count($result); if($len_result==0){ echo '没有任何数据!';exit; } $data_values = ''; for($i = 1; $i < $len_result; $i++){ //循环获取各字段值 $name = iconv('gb2312', 'utf-8', $result[$i][0]); //中文转码 $sex = iconv('gb2312', 'utf-8', $result[$i][1]); //$name = mb_convert_encoding($result[$i][0], "GBK", "UTF-8"); //$sex = mb_convert_encoding($result[$i][1], "GBK", "UTF-8"); $age = $result[$i][2]; $data_values .= "('$name','$sex','$age'),"; } $data_values = rtrim($data_values,','); //$data_values = substr($data_values,0,-1); //去掉最后一个逗号 fclose($handle); //关闭指针 $sql = "insert into ks_student (name,sex,age) values $data_values";//批量插入数据表中 $res = M()->execute($sql); if($res){ $xdata['status'] = '1'; $data = M("Student")->order("id desc")->select(); $xdata['info'] = $data; }else{ $xdata['status'] = '0'; $xdata['info'] = '导入失败!'; } echo json_encode($xdata);exit; }elseif($action=='export'){ //导出CSV //1、title $arrtitle = array("name"=>"姓名","sex"=>"性别","age"=>"年龄"); $str = ""; foreach($arrtitle as $value){ $str .= $value .","; } $str = rtrim($str,',')."\n"; //2、内容 $result = M("Student")->select(); $content = ''; foreach($result as $key=>$value){ foreach($arrtitle as $k=>$v){ $content .= $value[$k] .","; } $content = rtrim($content,",") . "\n"; } $type = 2; $filename = date('Y-m-d').'.csv'; //设置文件名 $string = iconv('utf-8','gb2312',$str.$content); //中文转码 //$string = mb_convert_encoding($str.$content, "GBK", "UTF-8"); if($type == 1){ file_put_contents($filename, $string);exit; }else{ //从浏览器输出 $this->export_csv($filename,$string); } /**简单导出方式********************************************** //1、title $str = "姓名,性别,年龄\n"; $str = iconv('utf-8','gb2312',$str); //$str = mb_convert_encoding($str, "GBK", "UTF-8"); //2、内容 $result = M("Student")->select(); foreach($result as $key=>$value){ $name = iconv('utf-8','gb2312',$value['name']); //中文转码 //$name = mb_convert_encoding($value['name'], "GBK", "UTF-8"); $sex = iconv('utf-8','gb2312',$value['sex']); //$sex = mb_convert_encoding($value['sex'], "GBK", "UTF-8"); $sex = $value['age']; $str .= $name.",".$sex.",".$sex."\n"; //用引文逗号分开 } $filename = date('Y-m-d').'.csv'; //设置文件名 file_put_contents($filename, $str); **************************************************************/ }else{ $this->error("错误操作!"); } } /*注意php自带的fgetcsv函数可以轻松处理csv, 使用该函数可以从文件指针中读入一行并解析CSV字段。 下面的函数将csv文件字段解析并以数组的形式返回*/ public function input_csv($handle){ $out = array (); $n = 0; while ($data = fgetcsv($handle, 10000)){ $num = count($data); for ($i = 0; $i < $num; $i++){ $out[$n][$i] = $data[$i]; } $n++; } return $out; } //输出到浏览器 public function export_csv($filename,$data){ 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 $data;exit; } }
注意导入和导出的过程中,因为我们使用的是统一UTF-8编码,遇到中文字符一定要记得转码,否则可能会出现中文乱码的情况。
本文为崔凯原创文章,转载无需和我联系,但请注明来自冷暖自知一抹茶ckhttp://www.cksite.cn