php 幾十萬數據導出到csv

參考資料 : https://blog.csdn.net/tim_phper/article/details/77581071 https://www.imooc.com/wenda/detail/316785php

/**
 * 下載/導出到csv文件
 * @param $title  標題欄標題
 * @param $data : array($count = M(表名)->where($where)->count(), $data_model = M(表名)->where($where)->order($order))
 * @param $sqlLimit  單文件容許寫入最大行
 * @param $mark  文件名標記信息名稱
 * @param $func  回調函數處理查詢出來的數據
 */
function downloadCsv(array $title, $data, $sqlLimit = 10000, $mark = 'test', $func = '')
{
    set_time_limit(0);
    $sqlCount = $data[0];
    $max_line_perfile = 100000;  //單文件容許寫入最大行
    // 輸出Excel文件頭,可把user.csv換成你要的文件名
    header('Content-Type: application/vnd.ms-excel;charset=utf-8');
    header('Content-Disposition: attachment;filename="' . $mark . '.csv' . '"');
    header('Cache-Control: max-age=0');

    //臨時文件的刪除處理
    $path = "./Upload/export/" . date('Ymd');
    //判斷目錄存在否,存在將刪除目錄下全部文件
    if (is_dir($path)) {
        rmdirr($path);
    } 
    if (!is_dir($path)) {
        //建立目錄
        mkdir(iconv("UTF-8", "GBK", $path), 0777, true);
    }

    //每次只從數據庫取最大數目以防變量緩存太大
    // 每隔$limit行,刷新一下輸出buffer,不要太大,也不要過小
    $limit = $sqlLimit;
    // buffer計數器
    $cnt = 0;
    $fileNameArr = array();
    // 逐行取出數據,不浪費內存
    for ($i = 0; $i < ceil($sqlCount / $sqlLimit); $i++) {
        $tmp_filename = $path . '/' . $mark . '_' . $i . '.csv';
        $fp = fopen($tmp_filename, 'w'); //生成臨時文件
       
        // chmod('attack_ip_info_' . $i . '.csv',777);//修改可執行權限
        $fileNameArr[] = $tmp_filename;
        // 將數據經過fputcsv寫到文件句柄
        foreach ($title as $key => &$value) {
            $value = iconv("UTF-8", "GBK", $value);
        }
        fputcsv($fp, $title);
                
        $dataArr = $data[1]->limit($i * $sqlLimit, $sqlLimit)->select();

        foreach ($dataArr as $a) {
            if($func) { $func($a); }
           
            //判斷是否爲多維數組來決定是一次寫幾行
            if(count($a) == count($a, 1)){  //一維數組
                if($sqlLimit > $max_line_perfile){
                    //限制一個文件不超過最大行
                    exit('下載單文件數目過大,請從新設置');
                }

                $cnt++;
                if ($limit == $cnt) {
                    //刷新一下輸出buffer,防止因爲數據過多形成問題
                    ob_flush();
                    flush();
                    $cnt = 0;
                }
                fputcsv($fp, $a);
            } else {
                if(($sqlLimit * count($a))  > $max_line_perfile){
                    //限制一個文件不超過100000行
                    exit('下載單文件數目過大,請從新設置');
                }

                foreach ($a as $a_v) {
                    $cnt++;
                    if ($limit == $cnt) {
                        //刷新一下輸出buffer,防止因爲數據過多形成問題
                        ob_flush();
                        flush();
                        $cnt = 0;
                    }
                    fputcsv($fp, $a_v);
                }
            }

            
        }
        fclose($fp);  //每生成一個文件關閉
    }
    //進行多個文件壓縮
    $zip = new ZipArchive();
    $filename = $path . '/' . $mark . ".zip";
    $zip->open($filename, ZipArchive::CREATE);   //打開壓縮包
    foreach ($fileNameArr as $file) {
        $zip->addFile($file, basename($file));   //向壓縮包中添加文件
    }
    $zip->close();  //關閉壓縮包
    foreach ($fileNameArr as $file) {
        unlink($file); //刪除csv臨時文件
    }
    //輸出壓縮文件提供下載
    header("Cache-Control: max-age=0");
    header("Content-Description: File Transfer");
    header('Content-disposition: attachment; filename=' . date('YmdHis').'_'.basename($filename)); // 文件名
    header("Content-Type: application/zip"); // zip格式的
    header("Content-Transfer-Encoding: binary"); //
    header('Content-Length: ' . filesize($filename)); //
    @readfile($filename);//輸出文件;
    unlink($filename); //刪除壓縮包臨時文件
}

引用片斷node

$title = array("ID\t","用戶名\t","幣種\t","變更資金\t","剩餘資金\t","日誌類型\t","行爲\t","日誌描述\t","IP\t","產生路徑\t","時間\t");

            $where = preg_replace('/a\./', 'c.', $where);
            $where = preg_replace('/b\./', 'd.', $where);
            $data_model = M('user_coinlog as c')->join('LEFT JOIN basanyi_user as d on c.userid = d.id')->where($where)->field('d.username,c.*')->order('c.id desc');

            downloadCsv($title, array($count, $data_model), 50000, 'user_trade', function(&$data){
                //數據處理顯示
                $data['add_time'] = addtime($data['add_time']);
             
                //排序並排除不須要的字段
                $tmp_data = [];
                $tmp_data[0] = $data['id'];
                $tmp_data[1] = $data['username'];
                $tmp_data[2] = $data['coin_name'];
                $tmp_data[3] = $data['effect'];
                $tmp_data[4] = $data['total'];
                $tmp_data[5] = $data['log_type'];
                $tmp_data[6] = iconv("UTF-8", "GBK", $data['action']);
                $tmp_data[7] = iconv("UTF-8", "GBK", $data['content']);
                $tmp_data[8] = $data['ip'];
                $tmp_data[9] = $data['node'];
                $tmp_data[10] = $data['add_time'];

                $data = $tmp_data;
            });
相關文章
相關標籤/搜索