PHP大数据导出Excel(CSV)方案

黎东
L、先森
2018-01-18 0 2151
<?php
/**
 * Created by PhpStorm.
 * User: lidong
 * Date: 2018/1/18
 * Time: 10:37
 */

class ExportCsv
{

    public static function putCsv(array $head = array(), array $data = array(), $fileName = "info")
    {
        set_time_limit(0);

        // 每隔$limit行,刷新一下输出buffer,不要太大,也不要太小
        $limit = 20000;
        // 逐行取出数据,不浪费内存
        $filePath = $fileName . '.csv';
        $fileExists = false;
        if (file_exists($filePath)) {
            $fileExists = true;

        }
        $fp = fopen($filePath, 'a'); //生成文件
        fwrite($fp, chr(0xEF) . chr(0xBB) . chr(0xBF)); // 添加 BOM
        if (!$fileExists) {
            fputcsv($fp, $head);
        }
        // buffer计数器
        $bufferNumber = 0;
        foreach ($data as $a) {
            $bufferNumber++;
            if ($limit == $bufferNumber) {
                //刷新一下输出buffer,防止由于数据过多造成问题
                ob_flush();
                flush();
                $bufferNumber = 0;
            }
            fputcsv($fp, $a);
        }
        fclose($fp);  //关闭
        return $filePath;
    }


    public static function compress($fileNameArr,$zipName = 'info')
    {
        //进行多个文件压缩
        $zip = new ZipArchive();
        $filename = $zipName . ".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=' . basename($filename)); // 文件名
        header("Content-Type: application/zip"); // zip格式的
        header("Content-Transfer-Encoding: binary"); //
        header('Content-Length: ' . filesize($filename)); //
        @readfile($filename);//输出文件;
        unlink($filename); //删除压缩包临时文件
    }

}

使用方法

$config = Config::get('application.common');
    $db = new Db((object)$config['db']);
    $sql = "SELECT COUNT(*) FROM t_column WHERE 1";
    $total = $db->single($sql);
    $limit = 100;
    $fileNameArr = array();
    $fileCount = 0;
    $readNum = 0;
    for ($i = 0; $i < ceil($total / $limit); $i++) {
        $head = array('column_name'=>'名称','column_label'=>'字段');
        $start = $i * $limit;
        $sql = "SELECT `column_name`,column_label
FROM
t_column
WHERE 1
limit {$start},{$limit}
";
        $data = $db->query($sql);
        //csv文件用EXCEL软件读取同样会存在只能显示104W的情况
        $readNum++;
        if(($readNum*$limit)>500){
            $readNum = 0;
            $fileCount++;
        }
        $fileName = 'info_'.$fileCount;
        $filePath = ExportCsv::putCsv($head,$data,$fileName);
        $fileNameArr[$fileCount] = $filePath;

    }
    ExportCsv::compress($fileNameArr);


php