资讯专栏INFORMATION COLUMN

关于PHP导出CSV文件的实现过程以及一些经常遇到的问题研究

用户83 / 2518人阅读

摘要:导出功能在管理后台算是比较常见的了。但是如果用来打开,超过行的数据都会看不见,这是程序的问题。本次导出数据量很大。原因数值显示精度为位造成精度丢失。

导出功能在管理后台算是比较常见的了。在实现导出表格类信息的功能时,可以选择两种实现方式:

导出为excel

导出为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    .=    "
";
        $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(",",""","
","	") 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."	"

或者

$strId."
"

需要注意的是,这样加是没有用的:

$strId." "

2.PHP运行时间的限制,导致程序被强制中断。
在不能随便改变php.ini文件里PHP运行的时间限制下,可以这样设置来增加运行时间:

set_time_limit(60*5);

3.默认内存设置太小,导致文件写入失败:
可以尝试这样解决

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

4.奇淫技巧
如果不想文件在读取或者写入的时候,因为用户的误操作被中断。可以通过如下参数实现:

ignore_user_abort(true);

以上是我自己在多次管理后台开发实现导出功能时曾经遇到过的问题,主页菌在此列出来希望可以和大家一起探讨一下。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/21988.html

相关文章

  • PHP+MySQL导出大量数据(Iterator yield)

    摘要:开发中经常遇到这样的场景产品汪我要在后台做一个功能,可以导出自定义时间范围的订单信息。结果,第二天一上班产品汪过来就是拍桌子,我想把去年一整年的订单都导出来,结果后台直接就挂了开发小哥一查,原来是内存溢出了,一年下来的的订单量足足有条。 开发中经常遇到这样的场景 产品汪:我要在后台做一个功能,可以导出自定义时间范围的订单信息。开发小哥二话不说,半天就把功能做完并上线了。结果,第二天一上...

    codergarden 评论0 收藏0
  • 实战PHP导出Excel-CSV文件

    摘要:中国大陆几乎所有的中文系统和国际化的软件都支持。与相应的国家标准中的其它汉字,以上合计个汉字。,全称国家标准信息技术中文编码字符集,是中华人民共和国现时最新的内码字集,是信息技术信息交换用汉字编码字符集基本集的扩充的修订版。 实战PHP导出Excel-CSV文件 导出后的效果 先给各位看一下导出的效果,而后再进行代码分析 showImg(https://segmentfault.co...

    Kyxy 评论0 收藏0
  • 实战PHP导出Excel-CSV文件

    摘要:中国大陆几乎所有的中文系统和国际化的软件都支持。与相应的国家标准中的其它汉字,以上合计个汉字。,全称国家标准信息技术中文编码字符集,是中华人民共和国现时最新的内码字集,是信息技术信息交换用汉字编码字符集基本集的扩充的修订版。 实战PHP导出Excel-CSV文件 导出后的效果 先给各位看一下导出的效果,而后再进行代码分析 showImg(https://segmentfault.co...

    molyzzx 评论0 收藏0

发表评论

0条评论

用户83

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<