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最后一行數據有一個\n,即最后會有一個空行。

<?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("/^\xEF\xBB\xBF/", '', $data);// ltrim($data, "\xEF\xBB\xBF");
    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操作功力的時候。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM