zoukankan      html  css  js  c++  java
  • PHP 百万级数据导出方案(多 CSV 文件压缩)

    ps:来源 :https://laravel-china.org/articles/15944/php-million-level-data-export-scheme-multi-csv-file-compression

    /**
         * 导出csv文件
         * @param $filename
         * @param $data
         * @param array $columns
         * @param int $chunk 限制每个文件条数
         */
        function exportCsv($filename, $data, $columns = [], $chunk = 10000)
        {
    
            header('Content-Type: application/csv; charset=UTF-8');
            header('Content-Disposition: attachment; filename="' . $filename . '.csv"');
            header('Cache-Control: max-age=0');
    
            $storageDir = rtrim(sys_get_temp_dir(), '/');
            $prefix = str_random(10);
    
            $fileList = []; // 文件集合
            $fileList[] = $file = "$storageDir/${prefix}_${filename}_1.csv";
    
            $fp = fopen($file, 'w');
            fputs($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));
            $head = array_pluck($columns, 'title');
            fputcsv($fp, $head);
    
            // 计数器
            $i = 0;
            // 每隔$limit行刷新一下输出buffer,不要太大,也不要太小
            $limit = 10000;
            // 行上限
            $maxLimit = 100000000;
    
            foreach ($data as $item) {
                if ($i >= $maxLimit) {
                    break;
                }
    
                if ($i > 0 && $i % $chunk == 0) {
                    fclose($fp);  // 关闭上一个文件
                    $j = $i / $chunk + 1;
                    $fileList[] = $file = "$storageDir/${prefix}_${filename}_$j.csv";
    
                    $fp = fopen($file, 'w');
                    fputs($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));
                    fputcsv($fp, $head);
                }
    
                $i++;
    
                if ($i % $limit == 0) {
                    ob_flush();
                    flush();
                }
    
                $row = [];
    
                foreach ($columns AS $column) {
                    $value = isset($column['key'])
                        ? (is_object($item) ? $item->{$column['key']} : $item[$column['key']])
                        : null;
                    $render = array_get($column, 'render');
                    if ($render && $render instanceof Closure) {
                        $row[] = $render($value, $item);
                    } else {
                        if (is_numeric($value) && strlen($value) > 10) {
                            $value .= "	";
                        }
                        $row[] = $value;
                    }
                }
    
                fputcsv($fp, $row);
                unset($row);
            }
    
            fclose($fp);
            if (count($fileList) > 1) {
                $zip = new ZipArchive();
                $oldFilename = $filename;
                $filename = "$storageDir/${prefix}_${filename}.zip";
                $zip->open($filename, ZipArchive::CREATE); // 打开压缩包
    
                foreach ($fileList as $file) {
                    $zip->addFile($file, str_replace("${prefix}_", '', basename($file)));   // 向压缩包中添加文件
                }
                $zip->close(); // 关闭压缩包
    
                foreach ($fileList as $file) {
                    @unlink($file); // 删除csv临时文件
                }
    
                // 输出压缩文件提供下载
                header("Cache-Control: max-age=0");
                header("Content-Description: File Transfer");
                header('Content-disposition: attachment; filename=' . $oldFilename . '.zip');
                header("Content-Type: application/zip"); // zip格式的
                header("Content-Transfer-Encoding: binary");
                header('Content-Length: ' . filesize($filename));
            } else {
                $filename = head($fileList);
            }
    
            @readfile($filename);
            @unlink($filename); // 删除临时文件
    
            exit;
        }
    
  • 相关阅读:
    Orderly Class
    POJ2513 【并查集+欧拉路径+trie树】
    POJ2195 Going Home【KM最小匹配】
    洛谷P2604 最大流+最小费用最大流
    小数转分数
    威尔逊定理
    luogu P6564 [POI2007] 堆积木KLO 树状数组+dp
    Codeforces Round #644 (Div. 3) H——Binary Median 二分
    luogu P4933 大师 线性dp
    Codeforces Round #643 (Div. 2) D——Game With Array
  • 原文地址:https://www.cnblogs.com/pcx105/p/9724787.html
Copyright © 2011-2022 走看看