PHP Excel 导入导出最简版:防卡死 / 防内存溢出,PHP7 + 直接用
- 2026-11-10 03:46:02
PHP Excel 导入导出最简版:防卡死 / 防内存溢出,PHP7 + 直接用
一、前置准备(2 步搞定) 1. 安装依赖(Composer 一行搞定) PhpSpreadsheet 是 PHPExcel 的官方升级版,兼容 PHP7+,性能更好: 若没有 Composer,直接下载压缩包:https://github.com/PHPOffice/PhpSpreadsheet/releases 2. 核心优化(防卡死 / 防内存溢出) 提前配置这几行,从根源避免问题: 二、Excel 导入导出最简封装类(核心) 无需复杂配置,封装成单文件,包含「导出、导入、大文件分批处理」核心功能: 三、完整使用示例(直接复制运行) 1. 基础导出(单 sheet / 小文件) 2. 大文件导出(分批处理,防溢出) 3. 基础导入(小文件) 4. 大文件导入(分批处理,防卡死) 5. 多 Sheet 导出 四、防坑指南(生产必看) 1. 内存溢出解决 2. 防卡死优化 3. 格式兼容 4. 前端配合(简单示例) 五、核心优化总结

大家好,我是专注 PHP 实战干货的博主。
做业务开发时,Excel 导入导出是高频需求,但新手常踩坑:大文件导入卡死、内存溢出、配置复杂、兼容问题。今天给大家带来PHP7+ 最简可行版,基于 PhpSpreadsheet(PHPExcel 官方替代),无需复杂配置,内置防卡死、防内存溢出优化,复制就能跑,支持大文件分批处理。
composer require phpoffice/phpspreadsheet "^1.29"<?php// 设置执行时间(防卡死,根据业务调整)set_time_limit(0);// 设置内存限制(防溢出,根据服务器配置调整)ini_set('memory_limit', '512M');// 禁用PhpSpreadsheet缓存(减少内存占用)define('SPREADSHEET_MEMORY_STORAGE', 'memory');
<?php/*** PHP Excel 导入导出最简封装类(PHP7+)* 特性:防卡死、防内存溢出、极简调用、支持大文件分批* 依赖:phpoffice/phpspreadsheet*/classExcelTool{/*** Excel 导出(支持多sheet、大文件分批)* @param array $data 导出数据 [['sheet名' => [表头[], 数据[]]]]* @param string $filename 文件名(无需后缀)* @param string $format 格式:xlsx/xls*/public static function export(array $data, string $filename = '导出数据', string $format = 'xlsx'){// 基础配置(防内存溢出)\PhpOffice\PhpSpreadsheet\Settings::setCacheStorageMethod(\PhpOffice\PhpSpreadsheet\Settings::CACHE_MEMORY);$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();$spreadsheet->removeSheetByIndex(0); // 删除默认sheet// 循环处理每个sheetforeach($data as $sheetName => $sheetData) {$sheet = $spreadsheet->createSheet();$sheet->setTitle($sheetName);// 写入表头$header = $sheetData[0];$col = 1;foreach($header as $h) {$sheet->setCellValueByColumnAndRow($col++, 1, $h);}// 分批写入数据(每1000行清理一次内存)$rows = $sheetData[1];$rowCount = 2;$batchSize = 1000;$total = count($rows);for($i = 0; $i < $total; $i += $batchSize) {$batch = array_slice($rows, $i, $batchSize);foreach($batch as $row) {$col = 1;foreach($row as $cell) {$sheet->setCellValueByColumnAndRow($col++, $rowCount, $cell);}$rowCount++;}// 清理内存gc_collect_cycles();}}// 下载响应头header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');header("Content-Disposition: attachment;filename=\"{$filename}.{$format}\"");header('Cache-Control: max-age=0');// 写入输出流(避免临时文件)$writer = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($spreadsheet, ucfirst($format));$writer->save('php://output');// 销毁对象,释放内存$spreadsheet->disconnectWorksheets();unset($spreadsheet);exit;}/*** Excel 导入(支持大文件分批读取)* @param string $filePath 文件路径* @param int $batchSize 分批大小(默认1000行)* @param callable $callback 每批数据的处理回调* @return array 总统计(成功行数/失败行数)*/public static function import(string $filePath, int $batchSize = 1000, callable $callback = null){if(!file_exists($filePath)) {throw new Exception('文件不存在');}// 基础配置\PhpOffice\PhpSpreadsheet\Settings::setCacheStorageMethod(\PhpOffice\PhpSpreadsheet\Settings::CACHE_MEMORY);$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReaderForFile($filePath);$reader->setReadDataOnly(true); // 只读取数据,不读取格式(减少内存)$reader->setLoadSheetsOnly(true); // 只加载需要的sheet$spreadsheet = $reader->load($filePath);$stats = ['success' => 0, 'fail' => 0];// 处理每个sheetforeach($spreadsheet->getSheetNames() as $sheetName) {$sheet = $spreadsheet->getSheetByName($sheetName);$highestRow = $sheet->getHighestRow();$highestCol = $sheet->getHighestColumn();$header = $sheet->rangeToArray("A1:{$highestCol}1")[0]; // 读取表头// 分批读取数据for($startRow = 2; $startRow <= $highestRow; $startRow += $batchSize) {$endRow = min($startRow + $batchSize - 1, $highestRow);$data = $sheet->rangeToArray("A{$startRow}:{$highestCol}{$endRow}");// 处理当前批次foreach($data as $row) {if(empty(array_filter($row))) continue; // 跳过空行try {// 回调处理数据(业务逻辑)if($callback) {$callback(array_combine($header, $row));}$stats['success']++;} catch(Exception $e) {$stats['fail']++;}}// 清理内存gc_collect_cycles();}}// 释放资源$spreadsheet->disconnectWorksheets();unset($spreadsheet);// 删除临时文件@unlink($filePath);return $stats;}}
<?phprequire_once 'vendor/autoload.php'; // Composer自动加载require_once 'ExcelTool.php';// 导出数据(表头 + 内容)$data = ['用户列表' => [['ID', '用户名', '手机号', '注册时间'], // 表头[1, '张三', '13800138000', '2026-03-04'],[2, '李四', '13900139000', '2026-03-05'],// 可追加任意多行]];// 一行导出ExcelTool::export($data, '用户数据', 'xlsx');
<?phprequire_once 'vendor/autoload.php';require_once 'ExcelTool.php';// 模拟10万行大数据(实际从数据库分批查询)$header = ['ID', '商品名', '价格', '库存'];$rows = [];for($i = 1; $i <= 100000; $i++) {$rows[] = [$i, "商品{$i}", rand(10, 100), rand(100, 1000)];}$data = ['商品列表' => [$header, $rows]];// 自动分批导出,无需额外配置ExcelTool::export($data, '十万条商品数据', 'xlsx');
<?phprequire_once 'vendor/autoload.php';require_once 'ExcelTool.php';// 上传文件处理(前端表单name="file")if($_FILES['file']['error'] === 0) {$tmpPath = $_FILES['file']['tmp_name'];// 导入并处理数据$stats = ExcelTool::import($tmpPath, 1000, function ($row) {// 业务逻辑:比如插入数据库echo "处理数据:" . json_encode($row) . "\n";// 示例:INSERT INTO user (name, mobile) VALUES (?, ?)});echo "导入完成:成功{$stats['success']}行,失败{$stats['fail']}行";}
<?phprequire_once 'vendor/autoload.php';require_once 'ExcelTool.php';// 处理50万行的大Excel$filePath = '/uploads/big_file.xlsx';// 分批导入,每1000行处理一次$stats = ExcelTool::import($filePath, 1000, function ($row) {// 批量插入数据库(推荐用PDO批量插入)static $batch = [];$batch[] = $row;// 每1000行执行一次批量插入if(count($batch) >= 1000) {// 示例:INSERT INTO goods (name, price) VALUES (?, ?)echo "批量插入1000行\n";$batch = [];}});echo "大文件导入完成:成功{$stats['success']}行,失败{$stats['fail']}行";
<?phprequire_once 'vendor/autoload.php';require_once 'ExcelTool.php';$data = ['用户表' => [['ID', '用户名'],[1, '张三'],[2, '李四']],'订单表' => [['订单ID', '用户ID', '金额'],[1001, 1, 99],[1002, 2, 199]]];ExcelTool::export($data, '多表数据', 'xlsx');
调整 ini_set('memory_limit', '1G')(根据服务器配置)减少 batchSize(比如从 1000 改为 500)开启 setReadDataOnly(true)(只读取数据,不读格式)
设置 set_time_limit(0)(无时间限制)分批读取 / 写入,避免一次性加载所有数据 数据库操作使用批量插入(不要单行插入)
优先使用 xlsx格式(比xls更省内存)避免合并单元格(解析会出错,建议拆分成普通单元格) 表头不要有空列(否则 array_combine 会报错)
<!-- 前端上传表单 --><formmethod="post"enctype="multipart/form-data"><inputtype="file"name="file"accept=".xlsx,.xls"><buttontype="submit">导入</button></form>
- 内存优化
禁用缓存、只读取数据、分批处理、及时销毁对象; - 防卡死
无时间限制、分批读写、批量数据库操作; - 极简调用
封装成 2 个核心方法,一行导出 / 导入; - 兼容性
支持 PHP7+、xlsx/xls、多 sheet、大文件; - 易扩展
回调函数处理业务逻辑,不耦合封装类。
关注我,后续我会继续分享:PHP 开发规范、框架实战、架构思路、运维技巧、效率工具。关注我,每天 3 分钟,提升开发效率。
欢迎在留言区告诉我:你在 Excel 导入导出中遇到过哪些坑?比如大文件处理、格式兼容、乱码等问题,我们一起交流解决方案!
本文来自网友投稿或网络内容,如有侵犯您的权益请联系我们删除,联系邮箱:wyl860211@qq.com 。