PHPExcel读取上传Excel并插入数据库遇问题求助
PHPExcel处理上传Excel文件的问题排查与解决方案
我来帮你拆解这段PHPExcel处理上传Excel代码里的潜在问题,再给出对应的修复方案:
1. 高危SQL注入漏洞(必须优先修复)
你直接把Excel读取到的$rpu和$kwh拼接进SQL语句,这是典型的SQL注入风险,恶意用户可以通过构造特殊内容篡改甚至删除你的数据库数据。
修复方案:使用MySQLi预编译语句
// 先准备预编译的插入语句 $stmt = $mysqli->prepare("INSERT INTO cs(rpu, kwh) VALUES(?, ?)"); // 绑定参数:第一个参数是类型标识(s=字符串,i=整数,根据你的字段类型调整),后面是要绑定的变量 $stmt->bind_param("ss", $rpu, $kwh); for ($i = 14; $i <= 39; $i++) { $rpu = $objPHPExcel->getActiveSheet()->getCell('E'.$i)->getValue(); $kwh = $objPHPExcel->getActiveSheet()->getCell('K'.$i)->getValue(); // 执行插入 $stmt->execute(); } // 记得关闭语句和数据库连接 $stmt->close();
2. 缺失错误处理,难以排查问题
你的代码没有任何异常捕获或错误检查,不管是Excel加载失败、数据库连接出错还是插入失败,都不会有任何提示,根本不知道问题出在哪。
修复方案:添加异常捕获与错误日志
try { // 先验证上传文件的有效性 if (!isset($file) || !file_exists($file)) { throw new Exception("上传文件不存在或路径错误"); } $objPHPExcel = PHPExcel_IOFactory::load($file); $objPHPExcel->setActiveSheetIndex(0); $stmt = $mysqli->prepare("INSERT INTO cs(rpu, kwh) VALUES(?, ?)"); if (!$stmt) { throw new Exception("创建预编译语句失败: " . $mysqli->error); } $stmt->bind_param("ss", $rpu, $kwh); for ($i = 14; $i <= 39; $i++) { $rpu = $objPHPExcel->getActiveSheet()->getCell('E'.$i)->getValue(); $kwh = $objPHPExcel->getActiveSheet()->getCell('K'.$i)->getValue(); // 可选:对数据做基础校验,跳过空数据 if (empty($rpu) || empty($kwh)) { error_log("第{$i}行数据为空,已跳过"); continue; } if (!$stmt->execute()) { error_log("第{$i}行插入失败: " . $stmt->error); } } $stmt->close(); echo "数据导入成功!"; } catch (Exception $e) { echo "导入失败:" . $e->getMessage(); error_log("Excel导入错误详情: " . $e->getMessage()); }
3. PHPExcel已停止维护,兼容性问题
PHPExcel早在2017年就停止更新了,如果你用的是PHP7.4及以上版本,很可能会出现语法错误或兼容性问题。官方推荐使用它的继任者PhpSpreadsheet。
修复方案:切换到PhpSpreadsheet
首先通过Composer安装依赖:
composer require phpoffice/phpspreadsheet
然后修改代码:
use PhpOffice\PhpSpreadsheet\IOFactory; try { // 验证上传文件 if ($_FILES['excel_file']['error'] !== UPLOAD_ERR_OK) { throw new Exception("文件上传失败,错误码: " . $_FILES['excel_file']['error']); } $file = $_FILES['excel_file']['tmp_name']; $spreadsheet = IOFactory::load($file); $worksheet = $spreadsheet->getActiveSheet(); $stmt = $mysqli->prepare("INSERT INTO cs(rpu, kwh) VALUES(?, ?)"); $stmt->bind_param("ss", $rpu, $kwh); for ($i = 14; $i <= 39; $i++) { $rpu = $worksheet->getCell('E'.$i)->getValue(); $kwh = $worksheet->getCell('K'.$i)->getValue(); $stmt->execute(); } echo "导入完成!"; } catch (Exception $e) { echo "导入失败:" . $e->getMessage(); }
4. 单元格值获取的特殊情况处理
如果Excel单元格里是公式或者日期格式,直接用getValue()可能得到的是公式本身或者序列化的日期数值,不是你需要的实际内容。
修复方案:处理公式与日期
- 对于公式:使用
getCalculatedValue()获取计算后的结果 - 对于日期:转换为可读的日期字符串
PHPExcel版本的处理:
// 获取公式计算后的值 $rpu = $objPHPExcel->getActiveSheet()->getCell('E'.$i)->getCalculatedValue(); // 处理日期格式 $cellK = $objPHPExcel->getActiveSheet()->getCell('K'.$i); if (PHPExcel_Shared_Date::isDateTime($cellK)) { // 转换为PHP时间戳,再格式化为需要的日期格式 $kwh = PHPExcel_Shared_Date::ExcelToPHP($cellK->getValue()); $kwh = date('Y-m-d H:i:s', $kwh); } else { $kwh = $cellK->getValue(); }
PhpSpreadsheet版本的处理:
use PhpOffice\PhpSpreadsheet\Shared\Date; // 获取公式计算后的值 $rpu = $worksheet->getCell('E'.$i)->getCalculatedValue(); // 处理日期格式 $cellK = $worksheet->getCell('K'.$i); if (Date::isDateTime($cellK)) { $kwh = Date::excelToDateTimeObject($cellK->getValue())->format('Y-m-d H:i:s'); } else { $kwh = $cellK->getValue(); }
5. 上传文件路径的正确性验证
要确保$file是正确的上传文件临时路径,不能直接用前端传来的文件名,必须从$_FILES数组获取:
// 假设前端表单的文件字段名为'excel_file' if ($_FILES['excel_file']['error'] === UPLOAD_ERR_OK) { $file = $_FILES['excel_file']['tmp_name']; } else { throw new Exception("文件上传失败:" . $this->getUploadError($_FILES['excel_file']['error'])); } // 可选:添加一个错误码转义函数 function getUploadError($code) { switch ($code) { case UPLOAD_ERR_INI_SIZE: return "上传文件超过php.ini限制的大小"; case UPLOAD_ERR_FORM_SIZE: return "上传文件超过表单限制的大小"; case UPLOAD_ERR_PARTIAL: return "文件仅部分上传"; case UPLOAD_ERR_NO_FILE: return "未选择上传文件"; default: return "未知上传错误"; } }
内容的提问来源于stack exchange,提问作者user8717594
相关产品推荐
相关产品推荐

