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

无法通过move_uploaded_file上传图片,请求故障排查建议

拖拽上传图片PHP报错排查

拖拽上传系统JS运行正常,但PHP端出现以下警告:

PHP Warning:  move_uploaded_file(assets/img/photos/1657614494809.jpg): failed to open stream: No such file or directory in /www_root/_inc/upload.php on line 29, referer: https://smartobchod.sk/bazar/add.php
[Sat Jul 23 12:56:18 2022] [error] [client 78.99.32.1] PHP Warning:  move_uploaded_file(): Unable to move '/home/gm016900/tmp/phpKaBL6m' to 'assets/img/photos/1657614494809.jpg' in /www_root/_inc/upload.php on line 29, referer: https://smartobchod.sk/bazar/add.php

2022年7月25日更新(已添加安全检查)

以下是upload.php中的PHP代码:

<?php

// 获取上传图片的引用
$image_file = $_FILES["file"];

// 获取图片名称
$image_name = $_FILES["file"]["name"];

// 获取文件大小
$image_size = $_FILES["file"]["size"];

// 若未上传文件或文件名包含非法字符/、\则终止
if ( ( !strpos($image_name, '/') || !strpos($image_name, '\\') ) && isset($image_file) ) {
    $errors = array();
    $maxsize = 10485760;
    $acceptable = array(
        'image/jpeg',
        'image/jpg',
        'image/gif',
        'image/png'
    );
} else {
    die('No image uploaded.');
}

// 若图片文件为空或大小超过10MB则终止
if (getimagesize($image_file["tmp_name"]) <= 0) {
    die('Uploaded file has no contents.');
} elseif ($image_size >= $maxsize) {
    die('Image is too large. Image must be less than 10 megabytes.');
}

// 若不是有效图片文件或格式不支持则终止
$image_type = exif_imagetype($image_file["tmp_name"]);

if (!$image_type) {
    die('Uploaded file is not an image.');
} elseif ( !in_array($image_file["type"], $acceptable) ) {
    die('Image has not supported type JPG, PNG, GIF.');
} else {
    $src = "default.png";
}

// 根据文件类型获取扩展名,第二个参数传true自动添加前缀点
$image_extension = image_type_to_extension($image_type, true);

// 创建唯一图片名称
$image_name = bin2hex(random_bytes(16)) . $image_extension;


// 文件存储路径
$relative_location = "/bazar/assets/img/photos/" . $image_name;

$absolute_location = dirname(__DIR__, 2) . $relative_location;

$return_arr = array();

// 将临时文件移动到图片存储目录
if (move_uploaded_file($image_file["tmp_name"], $absolute_location)) {
    
    $src = $relative_location;

    $return_arr = array("name" => $image_name,"size" => $image_size, "src"=> $src);
}

echo json_encode($return_arr);

发送至upload.php的请求头如下:

Content-Disposition: form-data; name="file"; filename="1657614494809.jpg"
Content-Type: image/jpeg

问题原因及解决方案

核心问题:目标目录不存在或权限不足

错误提示明确指出failed to open stream: No such file or directory,说明move_uploaded_file尝试写入的目录不存在,或者Web服务器进程没有该目录的写入权限。

具体排查与修复步骤:

  1. 验证目标路径正确性
    在move_uploaded_file前添加代码打印绝对路径,确认路径是否符合预期:

    echo $absolute_location; exit;
    

    比如dirname(__DIR__, 2)返回/www_root的话,完整路径应为/www_root/bazar/assets/img/photos/[文件名],需要确认该路径对应的物理目录真实存在。

  2. 自动创建缺失的目录
    如果目录不存在,在移动文件前递归创建目录并设置合理权限:

    $target_dir = dirname($absolute_location);
    if (!is_dir($target_dir)) {
        // 0755表示所有者可读可写可执行,其他用户可读可执行
        mkdir($target_dir, 0755, true);
    }
    
  3. 修复目录权限
    确保Web服务器进程(如www-data、apache)对目标目录有写入权限,可通过命令行设置:

    chown -R www-data:www-data /www_root/bazar/assets/img/photos/
    chmod -R 755 /www_root/bazar/assets/img/photos/
    
  4. 修正代码逻辑bug

    • 原安全检查逻辑错误:( !strpos($image_name, '/') || !strpos($image_name, '\\') )应改为( !strpos($image_name, '/') && !strpos($image_name, '\\') ),只要文件名包含/或\就应该拒绝上传。
    • getimagesize的判断逻辑不合理,该函数失败返回false,成功返回数组,应改为:
      if (!getimagesize($image_file["tmp_name"])) {
          die('Uploaded file has no contents or is not a valid image.');
      }
      

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 19:18:38