PHP处理Excel上传需通过$_FILES接收二进制文件流,校验错误码后移至安全目录,用PhpSpreadsheet解析并校验字段,清洗数据、查重、事务插入,返回结构化错误信息。

PHP 接收 multipart/form-data 上传的 Excel 文件
班级通信录通常以 Excel(.xlsx 或 .xls)形式批量提交,接口必须能正确接收并解析这类文件。关键不是“接收 POST 数据”,而是处理浏览器表单中 提交的二进制文件流。
-
$_FILES是唯一可靠入口,$_POST里不会出现 Excel 内容(除非前端错误地把 base64 当文本传) - 务必检查
$_FILES['file']['error'] === UPLOAD_ERR_OK,常见错误如UPLOAD_ERR_INI_SIZE(超出upload_max_filesize限制)需提前在 php.ini 调整 - 临时文件路径在
$_FILES['file']['tmp_name'],不能直接用file_get_contents($_POST['file'])—— 那会读空字符串或报错 - 推荐立即用
move_uploaded_file()移到安全目录(如/var/www/uploads/),避免被并发请求覆盖或清理
用 PhpSpreadsheet 解析 Excel 并校验字段结构
直接用 fgetcsv() 处理 Excel 会失败——它只支持 CSV。必须用支持 .xlsx 的库,PhpSpreadsheet 是当前最稳的选择(PHPExcel 已废弃)。
- 安装:用 Composer 加载
phpoffice/phpspreadsheet,别手动 require 类文件,否则命名空间报错 - 读取时指定输入类型:
$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');若要兼容.xls,改用'Xls'或先判断后分发 - 班级通信录常见字段如
姓名、学号、电话,需在代码里硬编码校验列名(如第一行是否含学号),缺失就中断导入并返回具体错误 - 避免全量加载:用
$reader->setReadDataOnly(true),跳过公式、样式等干扰,提速且防内存溢出
批量插入前做数据清洗和冲突检测
通信录导入不是“原样入库”,学生重复、电话格式非法、学号超长等问题必须拦截,否则脏数据直接污染数据库。
- 手机号统一用正则过滤非数字:
preg_replace('/\D/', '', $phone),再判断长度是否为 11(国内) - 学号去首尾空格,禁止为空或纯空格:
trim($studentId) === ''就标记该行失败 - 查重不能逐条
SELECT:先收集所有待导入学号,用WHERE student_id IN (...)一次性查出已存在记录,比对后返回重复列表 - 事务包裹插入:
$pdo->beginTransaction()→ 批量INSERT→ 成功则commit(),任一错则rollback(),防止部分写入
返回结构化错误信息给前端
前端需要知道哪几行失败、为什么失败,而不是笼统返回 “导入失败”。HTTP 状态码保持 200,错误详情放在响应 body 中。
立即学习“PHP免费学习笔记(深入)”;
- 不要用
die(json_encode([...])),用标准响应头:header('Content-Type: application/json; charset=utf-8') - 返回字段至少包含:
success(bool)、total(总行数)、imported(成功数)、errors(数组,每项含row行号、message错误原因) - 示例错误项:
["row": 5, "message": "电话格式错误:'abc-123'"],让前端可高亮第 5 行 - 大文件导入别超时:若耗时可能 >30s,建议加
set_time_limit(120),但更优解是队列异步处理(此为进阶,不在本次接口内)
真正难的不是读 Excel 或插数据库,而是字段语义理解——比如“班级”字段是填“高三(2)班”还是“302”?这必须和业务方对齐,并在导入前校验规则里写死。没人校验时,一个空格、一个全角数字、一个隐藏换行符,都能让整批数据卡住。











