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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:24:27