關於PHP導出CSV文件的實現過程以及一些常常遇到的問題研究

導出功能在管理後臺算是比較常見的了。在實現導出表格類信息的功能時,能夠選擇兩種實現方式:php

  1. 導出爲excelapi

  2. 導出爲csv文件格式數組

用csv方式導出,則能夠像導出txt同樣,以文本流的方式進行流式處理,不但能導出海量信息,並且流式處理佔用內存極低,服務器對瀏覽器的響應也是很是迅速的。理論上是不限量的。具體能導出多少條,是由服務器的響應時間、PHP的運行時間和內存等限制決定。可是若是用excel來打開csv,超過65536行的數據都會看不見,這是excel程序的問題。本次導出數據量很大。因此選擇csv。
整體實現思路爲:
先把須要導出的數據存到數組裏,而後寫入到文件。話很少說,仍是直接上代碼吧。瀏覽器

function export(){
    $data=array(
       array(
         'nId' => '90',
         'nick' => 'piapia',
       ),
       array(
         'nId' => '91',
         'nick' => 'monkey',
       )
     );
      $head = array(
         'nId' => 'id',
         'nick' => '暱稱',
    );
    
    $name = "filetoexport" . date('YmdHis', time());
    $this->writeCsvToBrowser($name, $head, $data);

}

function writeCsvToBrowser($filename,$headLine,$data,$lostData=array()) {
    $out    =    implode(',', $headLine);
    $out    =    iconv('UTF-8', 'GBK//IGNORE',$out);
    
    foreach ($data as $v) {
        $line    =    array();
        foreach (array_keys($headLine) as $objAttr) {
            if (is_object($v) && isset($v->$objAttr)) {
                $cellValue    =    $v->$objAttr;
            }elseif(is_array($v) && isset($v[$objAttr])) {
                $cellValue    =    $v[$objAttr];
            }else {
                $cellValue    =    $lostData[$objAttr];
            }
            $line[]    =    $cellValue;
        }
        $line = array_map('csvFormate',$line);
        $out    .=    "\n";
        $lineStr=    implode(',', $line);
        //iconv轉換編碼對字符串有長度限制,若是太長就會被截斷。
        $lineStr=    @iconv('UTF-8', 'GBK//IGNORE', $lineStr);
        $out    .=    $lineStr;
    }
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Content-Length: " . strlen($out));
    header("Content-type: text/x-csv");
    header("Content-Disposition:filename=$filename.csv");
    echo $out;
}


function csvFormate($str) {
    if (''===$str) {
        return '';
    }
    $find = FALSE;
    foreach (array(',','"',"\n","\t") as $v){
        if (FALSE===strpos($str, $v)) {
            $find = true;
            break;
        }
    }
    if (!$find) {
        return $str;
    }
    $str    =    str_replace('"', '""', $str);
    return sprintf('"%s"',$str);
}

在實現這個功能時,有一些問題須要你們注意一下。
1.精度丟失問題:
問題描述:導出後,發現有一個字段老是跟取得不同,Id爲1918553121332457在導出後變成1918553121332450,也就是說最後一位 老是變成了0。
緣由:Excel數值顯示精度爲15位形成精度丟失。
解決思路:強制轉化成字符串服務器

$strId."\t"

或者post

$strId."\n"

須要注意的是,這樣加是沒有用的:this

$strId." "

2.PHP運行時間的限制,致使程序被強制中斷。
在不能隨便改變php.ini文件裏PHP運行的時間限制下,能夠這樣設置來增長運行時間:編碼

set_time_limit(60*5);

3.默認內存設置過小,致使文件寫入失敗:
能夠嘗試這樣解決excel

ini_set('memory_limit','1024M');

4.奇淫技巧
若是不想文件在讀取或者寫入的時候,由於用戶的誤操做被中斷。能夠經過以下參數實現:code

ignore_user_abort(true);

以上是我本身在屢次管理後臺開發實現導出功能時曾經遇到過的問題,主頁菌在此列出來但願能夠和你們一塊兒探討一下。

相關文章
相關標籤/搜索