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

PHP上传入库报120秒最大执行时间超限致命错误排查

问题根因

你遇到的Fatal Error:Maximum execution time of 120 seconds is exceeded超时是代码逻辑错误触发死循环导致的,和服务器本身性能、大文件上传没有直接关系,具体问题点如下:

  • 核心死循环诱因:参数绑定逻辑存在设计缺陷
    你传入SQL参数绑定方法的$paramValue是带字符串键(:title/:descrip/:image)的关联数组,但bindQueryParams方法中用数字下标$i遍历数组取值。当PHP访问关联数组中不存在的数字索引时,会自动创建对应空元素,导致数组长度count($paramArray)随循环持续增长,循环变量$i永远无法满足终止条件,代码无限循环直到触发120秒的执行时间上限。你在addVideo开头写的ini_set('max_execution_time', 0)未生效,大概率是PHP开启了安全模式,该模式下脚本级别的执行时间配置修改会被拦截。
  • 重复执行SQL语句
    你自定义的prepare方法内部已经调用了$stmt->execute()执行SQL,但在addVideo方法中,调用完prepare后又额外调用了一次execute方法,重复执行插入逻辑不仅浪费资源,还会导致脏数据。
  • 无效死代码
    prepare方法中return $stmt之后写的header("location: ../header.php")永远不会执行,return语句会直接终止函数运行,后续代码全部属于无效逻辑。
  • 逻辑顺序颠倒
    你当前代码是先执行数据库插入操作,再校验标题等参数是否为空,会导致大量空数据写入数据表。
  • 表单配置缺失
    上传表单没有添加enctype="multipart/form-data"属性,文件上传功能完全不生效,$_FILES数组取不到上传的文件信息。
  • 上传逻辑不完整
    代码仅获取了上传文件的原始文件名,没有调用move_uploaded_file()把临时文件落地到存储目录,PHP会在请求结束后自动清理临时目录的上传文件。
修复方案

按以下步骤调整代码即可解决问题:

  1. 修复参数绑定的死循环问题
    在bindQueryParams方法中,先将传入的关联数组通过array_values()转为顺序索引数组,再进行遍历,避免不存在的数字下标触发数组自动扩容:
public function bindQueryParams($stmt, $paramType, $paramArray = array())
{
    ini_set('memory_limit', '-1');
    // 转为纯索引数组,消除死循环隐患
    $paramArray = array_values($paramArray);
    $paramValueReference[] = &$paramType;
    for ($i = 0; $i < count($paramArray); $i++) {         
        $paramValueReference[] = &$paramArray[$i];
    }
    call_user_func_array(array(
        $stmt,
        'bind_param'
    ), $paramValueReference);
}
  1. 调整业务逻辑顺序,移除重复执行
    把参数校验逻辑放到数据库操作之前,删除重复的execute调用,将跳转逻辑移到return语句之前:
public function addVideo(){
    ini_set('max_execution_time', 0);
    // 先取参数、做校验
    $title = $_POST["title"] ? trim($_POST["title"]) : "";
    $descrip = $_POST["descrip"] ? trim($_POST["descrip"]) : "";
    $image = $_FILES["image"]["name"] ? $_FILES["image"]["name"] : "";

    if(empty($title)) {
        $response["status"] = "error";
        $response["message"] = "Please enter a title";
        return $response;
    }
    if(empty($image)) {
        $response["status"] = "error";
        $response["message"] = "Please upload a valid file";
        return $response;
    }

    $sql = "INSERT INTO vidup (title, descrip, image) VALUES (?, ?, ?)";
    $paramType = "sss";
    // 按占位符顺序传索引数组,不要用字符串键
    $paramValue = array($title, $descrip, $image);

    // 仅调用一次prepare(内部已包含execute逻辑)
    $stmt = $this->ds->prepare($sql, $paramType, $paramValue);
    
    if($stmt) {
        // 补全文件落地逻辑,把临时文件移到你的存储目录
        // move_uploaded_file($_FILES["image"]["tmp_name"], "你的存储路径/".$image);
        $response["status"] = "success";
        $response["message"] = "Upload success";
        // 跳转逻辑放到方法最后,不要写在return后面
        header("location: ../upload_success.php");
        return $response;
    }

    $response["status"] = "error";
    $response["message"] = "Database insert failed";
    return $response;
}
  1. 补全表单的必要属性
    给form标签加上enctype="multipart/form-data",否则文件上传无法生效:
<form method="POST" enctype="multipart/form-data">
  <label>Name your video!</label>
  <input type="text" name="title" placeholder="Title" required>
  
  <label>Description</label>
  <input type="text" name="descrip" placeholder="Tell the viewers about your video" required>
  
  <label>Upload your file</label>
  <input type="file" name="image" required>
  <button type="submit" name="addVideo">UPLOAD</button>
</form>
  1. 清理prepare方法中的死代码
    把prepare方法里return后面的无效header逻辑删掉,避免后续维护产生误解:
public function prepare($query, $paramType, $paramArray)
{
    $stmt = $this->conn->prepare($query);
    $this->bindQueryParams($stmt, $paramType, $paramArray);
    $stmt->execute();
    return $stmt;
}

额外提示:如果是公网业务,不要直接用用户上传的原始文件名存文件,容易产生重名覆盖、路径穿越等安全问题,建议生成随机文件名存储。

内容的提问来源于stack exchange,提问作者Super David Gangster

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 11:00:59