使用PHP导入和导出CSV文件

        项目开发中,很多时候要将外部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编码,遇到中文字符一定要记得转码,否则可能会出现中文乱码的情况。

冷暖自知一抹茶ck
请先登录后发表评论
  • 最新评论
  • 总共0条评论