標籤:反饋 type pre ons debug query 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 可以輕鬆做到此事。
<?php$filename = $_FILES[‘cvsfile‘][‘tmp_name‘];//這裡的csvfile對應前端表單中的 input name="csvfile"$out = csv2arr($filename);//var_dump($out);//自己對資料進行處理,一般是反饋給前端讓使用者確認資訊是否正確 function csv2arr($filename){ $out = []; $handle = fopen($filename, ‘r‘); $n = 0; while ($data = fgetcsv($handle)){ $num = count($data); for ($i = 0; $i < $num; $i++){
//ANSI格式文本解析會出現亂碼,然後導致後續JSON轉換失敗
$data[$i] = mb_convert_encoding($data[$i], ‘utf-8‘, [‘gbk‘, ‘utf-8‘]); $out[$n][$i] = $data[$i]; } $n++; } return $out; }
注意:php裡面有內建完善的 fputcsv 和 fgetcsv 等函數,不要自己輕易盲目去實現csv格式的解析,裡面有不少坑,下篇JS處理時會講解。
不管php是不是世界上最好的語言,php就是有著世界上最全的函數庫→_→
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>
<?phpfunction csv2json(){ $filename = $_FILES[‘csvfile‘][‘tmp_name‘]; $out = csv2arr($filename); $this->ajaxReturn($out);}
這裡的互動應該比較容易看得懂,就是前端按鈕觸發Ajax提交檔案表單,然後後端轉換,並以JSON格式返回。最複雜的還是如何根據JSON填寫表單,不同的業務有不同的邏輯,這才是考驗前端DOM操作功力的時候。
PHP 和 JS 匯入匯出csv表格(上)