zoukankan      html  css  js  c++  java
  • PHP导出百万数据到Excel文件

    导出大容量的数据主要是因为持续占用内存,系统容易崩溃,下面我用过的两种办法都可以

    1.我们可以更改服务器配置,找到以下几个配置参数,让他导出的时候不会因为时间长挂掉

    fastcgi_connect_timeout 750000;  #链接
    fastcgi_read_timeout 600000;   #读取
    fastcgi_send_timeout 600000;   #发请求

    2 就是在导出过程中释放我们的缓存区

    先封装一个导出类包 xlsTools.php  (复制粘贴一把梭)

    <?php
    
    /*这个是类包*/
    
    class xlsTools{
        
        var $inEncode='utf-8';
        var $outEncode='gb2312';
    
        protected $rowCount; //存储已经存在内存中的记录条数
    
    
        protected $rowFlushCount; //  一次flush的数据条数
    
        public function __construct( $rowFlushCount = 1000 )
        {
                $this->rowFlushCount = $rowFlushCount;
                $this->rowCount = 0;
        }
    
        public function __destruct()
        {
            // TODO: Implement __destruct() method.
        }
    
        public function start($param){
            // todo 文件名这里建议允许自定 ddcoder
            $filename = $param['type'].'-'.date('YmdHis').'('.$param['name'].')';
            $this->doStart($param['title'],$filename);
        }
        public function doStart($keys,$filename){
            $this->download($filename.'.xls');
    
            // php输出到缓冲区
            echo '<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><style>td{vnd.ms-excel.numberformat:@}</style></head>';
            echo '<table width="100%" border="1">';
            // 有时候需要自定义表头 ddcdoer 修改于2017-08-26
            if ( $keys ) {
                echo '<tr><th filter=all>'.implode('</th><th filter=all>',$keys)."</th></tr>
    ";
            }
    
            //刷新缓冲区
            ob_flush();
            flush();
        }
        
        //下载文件
        //$mimeType = 'application/force-download'
        //Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
        //$mimeType = 'application/vnd.ms-excel'
        function download($fname = 'data', $data = null, $mimeType = 'application/force-download') {
            if (headers_sent($file, $line)) {
                echo 'Header already sent @ ' . $file . ':' . $line;
                exit();
            }
            //header('Cache-Control: no-cache;must-revalidate');
            // //fix ie download bug
            header('Pragma: no-cache, no-store');
            header("Expires: Wed, 26 Feb 1997 08:21:57 GMT");
            if (strpos($_SERVER["HTTP_USER_AGENT"], 'MSIE')) {
                $fname = urlencode($fname);
                header('Content-type: ' . $mimeType);
            } else {
                header('Content-type: ' . $mimeType . ';charset=utf-8');
            }
            header("Content-Disposition: attachment; filename="" . $fname . '"');
            //header( "Content-Description: File Transfer");
            if ($data) {
                header('Content-Length: ' . strlen($data));
                echo $data;
                exit();
            }
        }
        
        public function csv_export($keys , $expData , $type , $count)
        {
            $csv      = '';
            foreach ($keys as $key){
                $csv .= '"'.iconv("UTF-8", "gb2312",$key).'",';
            }
            $csv .= "
    ";
            
            foreach($expData as $expArr)
            {
                foreach ($expArr as $e_key=>$exp){
                    $csv .=  iconv("UTF-8", "gbk",$this->escapeCSV($expArr[$e_key])) . ',';
                }
                $csv .= "
    ";
            }
            ob_end_clean();
            $fileName = $type.'-'.date('YmdHis').'('.$count.').csv';
            header("Content-type:text/csv"); 
            header("Content-Disposition:attachment;filename=".iconv("UTF-8", "gb2312",$fileName)); 
            header('Cache-Control:must-revalidate,post-check=0,pre-check=0'); 
            header('Expires:0'); 
            header('Pragma:public'); 
            ob_end_clean();
            echo $csv;
        }
        
        /**
         * 生成并下载csv文件
         */
        public function csv_export_f($keys , $expData , $fileName)
        {
            // export file
            $csv      = '';
            foreach ($keys as $key){
                $csv .= '"'.iconv("UTF-8", "gb2312",$key).'",';
            }
            $csv .= "
    ";
             
            foreach($expData as $expArr)
            {
                foreach ($expArr as $e_key=>$exp){
                    $csv .=  iconv("UTF-8", "gbk",$this->escapeCSV($expArr[$e_key])) . ',';
                }
                $csv .= "
    ";
            }
            ob_end_clean();
            $fileName .= '.csv';
            header("Content-type:text/csv");
            header("Content-Disposition:attachment;filename=".iconv("UTF-8", "gb2312",$fileName));
            header('Cache-Control:must-revalidate,post-check=0,pre-check=0');
            header('Expires:0');
            header('Pragma:public');
            ob_end_clean();
            echo $csv;
        }
        
        function escapeCSV($str){
            $str = str_replace(array(',','"',"
    
    "),array('','""',''),$str);
            if($str == ""){
                $str = '""';
            }
            return $str;
        }
    
           public function allData($rows)
        {
            foreach($rows as $row){
                echo '<tr><td>'.implode('</td><td>',$row)."</td></tr>
    ";
            }
            ob_flush();
            flush();
        }
    
        public function oneData($row)
        {
            echo '<tr><td>'.implode('</td><td>',$row)."</td></tr>
    ";
            ob_flush();
            flush();
        }
    
        function end(){
            echo '</table>';
            ob_flush();
            flush();
        }
    
        /*
         * 多条数据flush一次 默认1000,有初始化对象决定
         * */
    
        public function multiData( $row )
        {
            $this->rowCount++;
            echo  '<tr><td>'.implode('</td><td>',$row)."</td></tr>
    ";
            if( $this->rowCount >= $this->rowFlushCount  )
            {
                ob_flush();
                flush();
            }
    
        }
    }

    类包封装完成后就可以写业务代码,导出的数据了

    <?php
    /*导出1000000万条数据实例*/
    
    
    /*导入类包*/
    require('xlsTools.php');
    
    /*实例化类包*/
    $xlsTools = new xlsTools();
    
    
    //定义列名和导出名称以及格式
    $xlsTools->start([
        'title'=>['列名1','列名2'],   //列名
        'type'=>'xls',               //导出的excel的类型
        'name'=>'导出'                //导出的excel的文件名
    ]);
    
    /* 导出100万条(1000000条)示例 */
    //这里可以是我们数据库查出来的数据,按照这种格式拼装即可
    for ($i=0; $i<1000000; $i++){
        $row = ['列值1'=>1,'列值2'=>'x'];
    
        //输出数据,并刷新缓冲区
        $xlsTools->oneData($row);
    }
    
    /*结束导出*/
    $xlsTools->end();

    按自己的业务需求查出数据使用即可

    注:虽然导出的数据不会崩溃,但是过百万的数据导出时间过长,需要配置服务器最大请求时间

  • 相关阅读:
    牛客网提高五练习
    [BZOJ2820]YY的GCD
    [BZOJ2301][HAOI2011]Problem B
    [板子]快速读入
    复选框改成开关样式,滑动切换(纯css实现)
    rem的使用方法
    html添加删除输入框
    jq 实现全选反选,获取选中的值
    cdn引入vant框架使用在html页面使用
    为什么vuejs里面定义的template模板里定义的多个元素只显示一个
  • 原文地址:https://www.cnblogs.com/bkhdd/p/15200498.html
Copyright © 2011-2022 走看看