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

PHP脚本中文件上传与数据库更新问题的排查与修复

问题排查与修复方案

原代码存在的核心问题

  • Session启动位置错误:session_start()必须在任何输出(包括include文件)之前调用,否则会导致Session无法正常读取。
  • 上传变量未初始化:$target_file和$uploaded仅在上传成功的分支中定义,无上传或上传失败时变量未定义,触发警告并导致路径判断逻辑出错。
  • 未保留原有图片路径:用户未上传新图时,代码会将pic字段设为空,直接覆盖数据库中原有图片路径。
  • 上传错误处理缺失:未检查profile_pictures目录是否存在、权限是否足够,也未处理move_uploaded_file的失败情况。
  • 重复数据库查询:代码前后两次查询用户资料,造成冗余。
  • 缺少文件安全验证:未校验上传文件的类型、大小,存在安全风险且可能上传无效文件。

修复后的完整代码

<?php
// 必须在任何输出前启动Session
session_start();

// 启用错误报告(建议仅开发环境使用)
error_reporting(E_ALL);
ini_set('display_errors', 1);

include 'db.php';

$nic = $_SESSION["nic"] ?? '';
$profile = null;
$error_message = '';

// 仅执行一次用户资料查询
if (!empty($nic)) {
    $stmt = mysqli_prepare($conn, "SELECT * FROM update_profile WHERE nic = ?");
    mysqli_stmt_bind_param($stmt, "s", $nic);
    mysqli_stmt_execute($stmt);
    $result = mysqli_stmt_get_result($stmt);
    if (mysqli_num_rows($result) > 0) {
        $profile = mysqli_fetch_assoc($result);
    }
    mysqli_stmt_close($stmt);
}

if (isset($_POST["submit"]) && !empty($nic)) {
    $email = trim($_POST["email"]);
    $school = trim($_POST["school"]);
    $mobile = trim($_POST["mobile"]);
    $stream = trim($_POST["subject_stream"]);
    $address = trim($_POST["address"]);
    $profile_pic = $_FILES["profile_pic"] ?? [];

    // 校验必填字段
    if (empty($email) || empty($school) || empty($mobile) || empty($stream) || empty($address)) {
        $error_message = "所有字段均为必填项。";
    } else {
        $uploaded = false;
        $target_file = '';
        $existing_pic = $profile['pic'] ?? '';
        $imageUrl = $existing_pic;

        // 处理图片上传(如果有上传)
        if (!empty($profile_pic) && $profile_pic['error'] == UPLOAD_ERR_OK) {
            // 定义上传目录
            $upload_dir = __DIR__ . DIRECTORY_SEPARATOR . 'profile_pictures' . DIRECTORY_SEPARATOR;
            
            // 检查目录是否存在,不存在则创建
            if (!is_dir($upload_dir)) {
                mkdir($upload_dir, 0755, true);
            }

            // 生成唯一文件名(避免重名)
            $file_ext = pathinfo($profile_pic["name"], PATHINFO_EXTENSION);
            $filename = $nic . '_' . uniqid() . '.' . $file_ext;
            $target_file = $upload_dir . $filename;

            // 验证文件类型(仅允许图片)
            $allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
            $file_type = mime_content_type($profile_pic["tmp_name"]);
            
            if (!in_array($file_type, $allowed_types)) {
                $error_message = "仅允许上传JPG、PNG、GIF格式的图片。";
            } elseif ($profile_pic["size"] > 2 * 1024 * 1024) { // 限制2MB以内
                $error_message = "图片大小不能超过2MB。";
            } else {
                // 执行文件上传
                if (move_uploaded_file($profile_pic["tmp_name"], $target_file)) {
                    $uploaded = true;
                    // 构建可访问的URL路径
                    $imageUrl = "/vv/std/profile_pictures/" . $filename;
                } else {
                    $error_message = "图片上传失败,请检查目录权限。";
                }
            }
        }

        // 仅在无上传错误时执行数据库更新
        if (empty($error_message)) {
            $stmt = mysqli_prepare($conn, "UPDATE update_profile SET email = ?, school = ?, mobile = ?, stream = ?, address = ?, pic = ? WHERE nic = ?");
            mysqli_stmt_bind_param($stmt, "ssissss", $email, $school, $mobile, $stream, $address, $imageUrl, $nic);
            
            if (mysqli_stmt_execute($stmt)) {
                mysqli_stmt_close($stmt);
                header("Location: profile.php");
                exit;
            } else {
                $error_message = "数据库更新失败: " . mysqli_stmt_error($stmt);
            }
        }
    }
}
?>

关键修复细节说明

  1. Session位置调整:将session_start()移至代码最顶部,确保Session正常读取。
  2. 变量初始化:提前初始化$uploaded、$target_file等变量,避免未定义警告。
  3. 保留原有路径:读取数据库中已有的图片路径,用户未上传新图时直接复用。
  4. 目录与权限处理:自动创建缺失的上传目录,确保服务器有写入权限。
  5. 文件安全校验:限制图片类型和大小,防止恶意文件上传。
  6. 唯一文件名:使用uniqid()生成唯一文件名,避免重名覆盖问题。
  7. 优化数据库操作:使用预处理语句避免SQL注入,合并重复查询减少冗余。

内容的提问来源于stack exchange,提问作者Hasala Kithmina

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 01:20:57