You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP-CodeIgniter实现临时Excel生成及批量打包Zip下载方案问询

实现可行性及操作指南

可行性结论

该需求完全可以基于PHP + CodeIgniter技术栈实现,核心依赖PHP原生ZipArchive扩展和Excel生成类库即可完成,无需接入额外外部服务。

前置准备

  • 确保PHP环境已开启ZipArchive扩展(绝大多数PHP集成环境默认已开启,可通过phpinfo()确认)
  • 引入PhpSpreadsheet作为Excel生成工具(性能优于老旧的PHPExcel,支持大文件写入优化,可通过Composer直接安装到CodeIgniter项目中)
  • 在CodeIgniter项目根目录创建两个权限为755的可写目录:temp_excel/ 用于存储临时分片Excel文件,temp_zip/ 用于存储最终打包的Zip压缩包

核心实现步骤

步骤1:分批查询数据库,避免一次性读取全量数据

通过CodeIgniter查询构造器的分页能力,按预设的单文件行数分批拉取数据,避免内存溢出:

// 先统计总数据量
$totalRows = $this->db->count_all('你的业务数据表名');
// 单Excel文件存储行数,可根据服务器配置调整,示例为5万行
$perPage = 50000;
$totalShard = ceil($totalRows / $perPage);
// 存储所有生成的临时Excel路径
$excelShardList = [];

步骤2:循环生成分片Excel临时文件

每拉取一批数据就生成一个独立的Excel文件,生成完成后立即清理内存,避免内存占用持续升高:

// 加载PhpSpreadsheet自动加载文件(Composer安装场景)
require_once APPPATH . 'vendor/autoload.php';
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

for ($i = 0; $i < $totalShard; $i++) {
    // 分页拉取数据
    $offset = $i * $perPage;
    $currentData = $this->db->limit($perPage, $offset)->get('你的业务数据表名')->result_array();
    
    $spreadsheet = new Spreadsheet();
    $activeSheet = $spreadsheet->getActiveSheet();
    $startRow = 1;
    // 仅第一个分片写入表头,不需要的话可以去掉该逻辑
    if ($i == 0) {
        $activeSheet->setCellValue('A1', '字段1名称');
        $activeSheet->setCellValue('B1', '字段2名称');
        // 补充其余表头字段
        $startRow = 2;
    }
    // 写入当前分片数据
    foreach ($currentData as $index => $row) {
        $currentRow = $startRow + $index;
        $activeSheet->setCellValue('A'.$currentRow, $row['字段1']);
        $activeSheet->setCellValue('B'.$currentRow, $row['字段2']);
        // 补充其余字段写入逻辑
    }
    // 保存临时Excel文件
    $tempExcelPath = FCPATH . 'temp_excel/数据分片_'.($i+1).'.xlsx';
    $writer = new Xlsx($spreadsheet);
    $writer->save($tempExcelPath);
    $excelShardList[] = $tempExcelPath;
    
    // 手动清理当前分片的内存占用
    $spreadsheet->disconnectWorksheets();
    unset($spreadsheet, $currentData, $writer);
}

步骤3:打包所有分片Excel为Zip压缩包

所有分片生成完成后,将所有临时Excel文件打包为一个Zip压缩包:

$zipFileName = '全量数据导出_'.date('YmdHis').'.zip';
$zipFilePath = FCPATH . 'temp_zip/'.$zipFileName;
$zip = new \ZipArchive();
if ($zip->open($zipFilePath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) === true) {
    foreach ($excelShardList as $excelPath) {
        $zip->addFile($excelPath, basename($excelPath));
    }
    $zip->close();
}

步骤4:触发用户下载并清理临时文件

输出压缩包给用户下载,完成后删除所有临时文件,避免占用服务器存储空间:

// 设置下载响应头
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename='.$zipFileName);
header('Content-Length: '.filesize($zipFilePath));
readfile($zipFilePath);

// 清理所有临时文件
foreach ($excelShardList as $excelPath) {
    unlink($excelPath);
}
unlink($zipFilePath);
exit;

优化建议

  • 如果数据量超过千万级,建议将导出任务改为异步队列处理:用户触发导出后先返回待处理提示,后台静默生成压缩包后再通知用户下载,避免前端请求超时
  • 可根据服务器配置调整单Excel的存储行数,配置较低的服务器可将$perPage调整为20000-30000,进一步降低单批次处理压力
  • 查询数据库时可使用unbuffered_row遍历结果集,进一步降低内存开销
  • 导出逻辑中避免加载CodeIgniter不必要的类库,减少额外内存占用

内容的提问来源于stack exchange,提问作者Parikshit Bharadwaj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 20:06:05