zoukankan      html  css  js  c++  java
  • csv表格处理(上)-- JS 与 PHP 协作导入导出

    CSV简介

    在开发后台管理系统的时候,几乎无可避免的会遇到需要导入导出Excel表格的需求。csv也是表格的一种,其中文名为“逗号分隔符文件”。在Excel中打开如下图左边所示,在记事本打开如下图右边所示:

    再看包含特殊字符的表格

    与xls或xlsx 表格相类似,CSV文件也是用来表示二维表格。而不同的是:
    1、CSV是一种纯文本文件,任何编辑器都能打开并读取它;xls(x)是专用的二进制文件,要用表格软件才能正常打开,否则乱码;
    2、CSV的体积很小,比如上面的表格内容,csv只有几十b;而xlsx有8k,老格式xls则有18k;
    3、CSV的表达能力有限,只能表示二维数组(或一维);xls(x)等则有各种文件配置等等信息;可以参考JSON与XML的对比。

    再看CSV的格式特点:
    1、一般情况下,以逗号分隔一维数组(列),以换行分隔二维数组(行)。
    2、当表格内容有,半角逗号、换行、空格、tab 等特殊字符时,外面使用双引号括起来。
    3、当表格内容有"双引号时,转换为两个""双引号,外面用双引号括起来。
    4、最后可以有空行,或者没有空行。

    CSV格式详情参考这个标准:rfc4180

    PHP导出CSV

    导出Excel几乎是管理后台的标配功能。PHP能非常方便地设置HTTP header,控制输出的形式,而二维数组转换成CSV字符串也有成熟的函数库处理,没太大技术难点,直接贴源码。要注意的是此方式导出的CSV最后一行数据有一个 ,即最后会有一个空行。

    <?php
        /**
         * 导出为CSV格式
         * @param string $filename 文件名,含后缀
         * @param array $arr2D 表数据,二维数组
         * @return 直接生成文件,用a标签跳转过来。本函数用了exit;以去除框架附加的debug信息
         * */    
        function export_csv($filename, $arr2D){
            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');
    
            $fp = fopen('php://output', 'w');//取自PHP官网的评论,直接输出文本
            foreach ($arr2D as $lines) {
                fputcsv($fp, $lines);
            }
            fclose($fp);
            exit;
        }

    稍微说明一下:
    1、HTTP header设置为 text/csv 则表示此文件是CSV格式文件以给浏览器处理,调用此函数前不要有其它输出;
    2、参数 $filename 是你要设置的下载的文件名(如:test.csv),参数 $arr2D 是要生成CSV的二维数组,CSV只支持二维数组;

    PHP导入CSV

    PHP导入CSV也非常简单,php也有内置函数帮助处理。值得留意的是,此函数会自动去掉CSV最后的换行符(空行)

    中文编码问题,我们通常网站和数据库都是使用UTF8编码,最常使用的JSON也是UTF8编码。但是Excel等软件是基于微软生态的,在中国通常是以GBK(含GB2312)编码,如果不进行转换编码的话,会导致后续的使用不便、JSON转换数据出错等等问题。而用户的文件上传也没法保证是utf8的还是gbk的,所以都需要兼容,PHP有个内置方法 mb_convert_encoding 可以轻松做到此事。

    UTF8的BOM头问题,因为PHP默认没有处理BOM头,会导致带BOM头UTF8的csv文件解析首行出BUG,所以要先处理一下。

    <?php
    $filename = $_FILES['cvsfile']['tmp_name'];//这里的csvfile对应前端表单中的 input name="csvfile"
    $out = csv2arr($filename);
    //var_dump($out);
    //自己对数据进行处理,一般是反馈给前端让用户确认信息是否正确
    
    
    function csv2arr($filename){
        //去除BOM头
        $data = file_get_contents($filename);
        preg_replace("/^xEFxBBxBF/", '', $data);// ltrim($data, "xEFxBBxBF");
        file_put_contents($filename, $data);
    
        $out = [];
        $handle = fopen($filename, 'r');
        $n = 0;
        while ($data = fgetcsv($handle)){
            $num = count($data);   
            for ($i = 0; $i < $num; $i++){
                //ANSI格式文本解析会出现乱码,然后导致后续JSON转换失败 
                //注意编码列表的顺序,GBK 或 GB18030 放在utf8前面会导致utf8文件中文转换乱码   
                $data[$i] = mb_convert_encoding($data[$i], 'utf-8', ['utf-8', 'GB18030', 'BIG-5']);  
                $out[$n][$i] = $data[$i];
            }
            $n++;
        }
        return $out;
    }

    注意:php里面有内置完善的 fputcsvfgetcsv 等函数,不要自己轻易盲目去实现csv格式的解析,里面有不少坑,下篇JS处理时会讲解。

    JS与PHP的互动

    一个Excel表的导入流程是这样的:

      选择表格 --> 解析表格 --> 填充数据到表单 --> 用户检查 --> 提交表单

    其中“解析表格 --> 填充数据到表单”这一步有几种方案:

    一、上传csv文件到服务器,解析并生成整个表单页面给前端;

    二、上传csv文件到服务器,解析返回JSON,前端JS填充表单;

    三、前端JS本地解析csv文件生成JSON,然后填充表单;

    其中第三个方案要现代H5浏览器才能实现,而且比较复杂,具体会在下一篇文章再讲。现在简单介绍第二个方案。

    <form action="Test/csv2json" method="post" >
        <input type="file" name="csvfile" />
    </form>
    <input type="button" onclick="csv1()" value="后台转换"/>
    <script src="jquery.js"></script>
    <script src="jquery.form.js"></script>
    <script>
    function csv1(){
        $("input[name=csvfile]").parent("form").ajaxSubmit(function(res){
            console.log( res );
            //TODO:这里是根据业务需要做的处理
            writeForm( res );
        });
    }
    </script>
    <?php
    function csv2json(){
        $filename = $_FILES['csvfile']['tmp_name'];
        $out = csv2arr($filename);
        $this->ajaxReturn($out);
    }

    这里的交互应该比较容易看得懂,就是前端按钮触发Ajax提交文件表单,然后后端转换,并以JSON格式返回。最复杂的还是如何根据JSON填写表单,不同的业务有不同的逻辑,这才是考验前端DOM操作功力的时候。

  • 相关阅读:
    mangoDB
    python文档
    单例模式
    celery
    flask 部署
    json
    Docker+Jenkins+Go完成自动化部署
    Go多协程循环打印ABAC
    正则表达式
    从零开始学Go之并发(四):互斥
  • 原文地址:https://www.cnblogs.com/batsing/p/csv1.html
Copyright © 2011-2022 走看看