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

  • 相关阅读:
    win10 ObservableCollection 排序自动收缩问题
    在C#中GUID生成的四种格式
    MultiBinding的StringFormat参数问题
    asp.net mvc cookie超时返回登录页面问题
    string.Format的困惑
    c# web应用调试开启外部访问
    主码索引、聚集索引、非主码索引(辅助索引)、唯一索引、外键索引、复合索引、非主码索引、聚集主码(聚集索引)、单列索引、多列索引、普通索引等
    优化MD5和IP在(MySQL)数据库中的存储
    《Effective MySQL之SQL语句最优化》读书笔记——乱七八糟系列(给自己看)
    布隆过滤器(Bloom Filter)文章收集
  • 原文地址:https://www.cnblogs.com/lalalagq/p/9980060.html
Copyright © 2011-2022 走看看