zoukankan      html  css  js  c++  java
  • PHP导出超大的CSV格式的Excel表方案

    场景和痛点

    说明

    我们工作场景都常会导出相关的excel数据,有时候需要大量的数据,10W,100W都有可能

    我们现有方案都是直接利用phpexcel等类库来操作,phpexcel的load加载或是写入一次导出会遇到超时内存和时间限制问题,就算我们ini_set依旧不是最好的方案

    下面我们利用php输出csv,把数据依次输出清空再输出的方式到输出终端(浏览器访问就是浏览器输出)

    编写过程

    说明

    关键具体在代码里注释

    代码

    
    <?php
    /**
     * Created by PhpStorm.
     * User: qkl
     * Date: 2018/7/11
     * Time: 13:28
     */
    ini_set('display_errors', 1);
    //error_reporting(E_ALL);
    
    function convert($size)
    {
        $unit = array('b', 'kb', 'mb', 'gb', 'tb', 'pb');
        return @round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) . ' ' . $unit[$i];
    }
    
    header('Content-Type: application/vnd.ms-excel');
    header('Content-Disposition: attachment;filename=xxxxxxxxx.csv');
    header('Cache-Control: max-age=0');
    
    set_time_limit(0);   // 设置脚本最大执行时间 为0
    //ini_set('memory_limit','200M');    // 临时设置最大内存占用
    
    //关闭缓冲区
    $flag = ob_end_clean();
    if (!$flag) {
        die("关闭缓冲区错误");
    }
    
    $startTime = microtime(true);
    
    //$status = ob_get_status();
    //file_put_contents("11.log", var_export($status, 1).PHP_EOL, 8);
    
    // 打开PHP文件句柄,php://output 表示直接输出到浏览器
    $fp = fopen('php://output', 'a');
    
    $column_name = ["XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX", "XXX"];
    // 将中文标题转换编码,否则乱码
    foreach ($column_name as $i => $v) {
        $column_name[$i] = iconv('utf-8', 'GBK', $v);
    }
    
    // 将标题名称通过fputcsv写到文件句柄
    fputcsv($fp, $column_name);
    
    $export_data = [];
    for ($i = 0; $i < 10; $i++) {
        foreach (range(1, 100000) as $k => $v) {
            $export_data[] = [
                "XXX" . $v, "XXX" . $v, "XXX" . $v, "XXX" . $v, "XXX" . $v, "XXX" . $v, "XXX" . $v, "XXX" . $v, "XXX" . $v, "XXX" . $v
            ];
        }
        foreach ($export_data as $item) {
            $rows = array();
            foreach ($item as $export_obj) {
                $rows[] = iconv('utf-8', 'GBK', $export_obj);
            }
            fputcsv($fp, $rows);
        }
    
        $export_data = []; //重新复制,释放掉旧数据
    }
    fclose($fp);
    
    $endTime = microtime(true);
    $memoryUse = memory_get_usage();
    
    file_put_contents("11.log", "内存占用:" . convert($memoryUse) . "; 用时:" . ($endTime - $startTime) . PHP_EOL, 8);
    
    exit(0);
    

    结果

    测试说明

    我们模拟数据,输入了100万(10000 * 10)数据

    日志记录内存使用率

    
    # 文件大小:84.7 MB (88,889,540 字节)
    # 这里的用时因为业务模拟,所以具体根据操作业务数据可能会更长,内存占用同理
    
    内存占用:118.99 kb; 用时:74.375253915787
    

    原文地址:https://segmentfault.com/a/1190000015601266

  • 相关阅读:
    el-select下拉框选项太多导致卡顿,使用下拉框分页来解决
    vue+elementui前端添加数字千位分割
    Failed to check/redeclare auto-delete queue(s)
    周末啦,做几道面试题放松放松吧!
    idea快捷键
    解决flink运行过程中报错Could not allocate enough slots within timeout of 300000 ms to run the job. Please make sure that the cluster has enough resources.
    用.net平台实现websocket server
    MQTT实战3
    Oracle 查看当前用户下库里所有的表、存储过程、触发器、视图
    idea从svn拉取项目不识别svn
  • 原文地址:https://www.cnblogs.com/lalalagq/p/9980060.html
Copyright © 2011-2022 走看看