PHP---导出百万大数据【解决方案】

最近开发项目,遇到一个问题,通常导出数据我们都会使用 PHPExcel 来导出数据,但是遇到大数据,这个方法就不行了。

例如:我的项目,3.5W个学生信息,需要导出做数据备份,使用【PHPExcel】来导出就不行了,需要另谋它法:

不考虑PHPExcel就只能考虑导出CSV:

具体实现思路:

按照一定的数量,例如:5000条,导出CSV文件,多个CSV文件进行压缩为ZIP,最后导出ZIP里面就有所有数据。例如:3.5w条数据,最终有5个CSV文件,生成一个ZIP压缩文件。

代码:

public function exportCSV()
{
    $limit = 5000;//每次只从数据库取50000条以防变量缓存太大
    // buffer计数器
    $cnt = 0;
    $xlsTitle = ['序号','姓名','性别'];
    /******************** 调整位置开始 ***************************/
    $sqlCount = 3000; // 这里需要查询出总条数
    /******************** 调整位置结束 ***************************/
    $fileName = iconv('utf-8', 'gb2312', 'students');//文件名称
    $fileName = $fileName . date('_YmdHis');// 文件名称可根据自己情况设定
    $zipname = 'zip-' . $fileName . ".zip";
    // 输出Excel文件头,可把user.csv换成你要的文件名
    header('Content-Type: application/vnd.ms-excel;charset=utf-8');
    header('Content-Disposition: attachment;filename="' . $zipname . '"');
    header('Cache-Control: max-age=0');
    $fileNameArr = array();
    // 逐行取出数据,不浪费内存
    for ($i = 0; $i < ceil($sqlCount / $limit); $i++) {
        $fp = fopen($fileName . '_' . ($i+1) . '.csv', 'w'); //生成临时文件 
        // chmod('attack_ip_info_' . $i . '.csv',777);//修改可执行权限 
        $fileNameArr[] = $fileName . '_' . ($i+1) . '.csv'; // 将数据通过fputcsv写到文件句柄 
        fputcsv($fp, $xlsTitle);
        $start = $i * $limit;
        /******************** 调整位置开始 ***************************/
        $dataArr = $this->model->getList($start,$limit); // 每次查询limit条数据
        /******************** 调整位置结束 ***************************/
        foreach ($dataArr as $a) {
            $cnt++;
            if ($limit == $cnt) {
                // 刷新一下输出buffer,防止由于数据过多造成问题
                ob_flush();
                flush();
                $cnt = 0;
            }
            fputcsv($fp, $a);
        }
        fclose($fp); // 每生成一个文件关闭
    }

    // 进行多个文件压缩
    $zip = new \ZipArchive();
    $zip->open($zipname, $zip::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-Type: application/zip"); // zip格式
    header("Content-Transfer-Encoding: binary");
    header('Content-Length: ' . filesize($zipname));
    @readfile($zipname); // 输出文件
    unlink($zipname); // 删除压缩包临时文件
}

参考:

https://cloud.tencent.com/developer/article/1990268

打完收工!

posted @ 2022-09-02 15:12  帅到要去报警  阅读(265)  评论(0编辑  收藏  举报