webman中excel百万行导入需异步解耦:上传后仅校验并存临时文件,元数据写入任务表;用redis队列驱动cli worker分块解析(如spout流式读取),每批5000行批量入库并事务提交,支持断点续传与错误隔离。

Webman 里直接同步读 Excel 入库百万行,基本必崩——内存爆、超时、卡死全来。必须拆开“上传”“解析”“入库”三个环节,用异步解耦。
Webman 怎么把 Excel 上传和解析分离
用户上传文件后,Webman 控制器不该立刻调用 PhpSpreadsheet 解析。正确做法是:只校验文件类型和大小,保存原始文件到临时目录(如 /runtime/uploads/),然后立即返回“已收到,正在处理”。关键点:
- 上传路径必须可写,且 Webman 进程用户(如 www-data)有权限读取;
- 文件名要重命名(如
import_+uniqid()+.xlsx),避免冲突或路径遍历; - 原始文件路径、目标表名、字段映射规则等元数据,存入数据库任务表(如
import_tasks),带status字段(pending/running/failed/success); - 不要在 HTTP 请求生命周期内做任何耗时操作,否则会阻塞 Worker 进程。
用 Redis 队列驱动后台导入 Worker
Webman 自身不带常驻进程管理,得靠外部 Worker 消费队列。推荐用 Redis List + PHP CLI 脚本组合,比 cron 扫表更实时、比 exec + nohup 更可控。
- 控制器上传完成后,用
$redis->lpush('import_queue', json_encode($task))推入任务; - 写一个独立的 CLI 脚本(如
php bin/import-worker.php),用BRPOP import_queue 0阻塞监听; - Worker 中先
set_time_limit(0)和ini_set('memory_limit', '512M'),但别设为-1——防止失控吃光内存; - 每处理完一批(如 5000 行),更新一次
import_tasks.status和progress字段,方便前端轮询进度; - Worker 必须捕获所有异常,并写入日志(如
error_log("导入失败: $e", 3, '/runtime/logs/import-error.log')),失败后标记任务为failed,不重试。
百万行 Excel 解析不能用全量 load
Worker 里若还用 IOFactory::load($file),照样 OOM。必须启用分块读或换库:
- 用
PhpSpreadsheet的ChunkReadFilter:设置$reader->setReadFilter(new ChunkReadFilter($startRow, $endRow)),每次只读 1000 行,循环调用; - 更稳的选择是
box/spout:它天生流式,$reader->open($file)后直接getRowIterator(),内存稳定在 5–10MB,但不支持公式和样式; - 如果 Excel 结构固定,优先转 CSV:用系统命令
ssconvert --export-type=Gnumeric_stf:stf_csv $xlsx_path $csv_path,再用fgetcsv()逐行读——零依赖、最快、最省内存; - 注意:无论哪种方式,都要跳过空行、校验必填字段、转换日期(
Date::excelToDateTimeObject())、强转字符串((string)$cell->getValue()防 null)。
入库必须批量 + 事务 + 分批提交
单条 INSERT 百万次?网络往返和事务开销直接拖垮 MySQL。真实场景下:
- 每 1000 行组装一个
INSERT INTO ... VALUES (...), (...), (...)语句,最多别超 5000 行,避免 SQL 过长被截断; - 用 PDO 开启事务:
$pdo->beginTransaction(),插入完一批就$pdo->commit(),出错则rollback(); - 别用 ORM 批量插入(如 Laravel 的
insert()),它会生成冗余 SQL 或自动分页,反而慢; - 如果表无唯一约束且数据干净,
LOAD DATA INFILE是终极方案——但要求 CSV 文件在 MySQLsecure_file_priv目录下,且 Webman 进程有权限移动文件过去。
真正容易被忽略的是错误恢复能力:任务中断后,得能从断点续传,而不是重头再来。这意味着解析阶段必须记录当前处理到第几行,入库阶段要加唯一索引或先查后插,避免重复数据。这些细节不提前设计,上线后半夜救火就是常态。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











