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

PHP图片上传异常:文件路径无效但文件实际存在

解决「文件名/路径无效」与「Invalid file format」问题

先看你的错误栈,核心问题是finfo::file()调用时传入了空的临时文件路径,这才导致后续抛出「Invalid file format」异常——不是真的文件格式有问题,而是上传流程中出现了未被捕获的错误,导致代码错误地走到了格式校验步骤。我们一步步来修复:

1. 补全上传错误的判断逻辑

你的switch语句只处理了3种上传错误,但PHP的文件上传错误码还有其他场景(比如文件超过表单设定大小、临时目录不可写等)。当这些未被处理的错误发生时,代码会继续往下执行,但此时$_FILES['fileToUpload']['tmp_name']是空的,直接触发finfo->file()的警告。

把switch部分修改成下面这样,覆盖所有上传错误场景:

switch ($_FILES['fileToUpload']['error']) {
    case UPLOAD_ERR_OK:
        break;
    case UPLOAD_ERR_NO_FILE:
        throw new RuntimeException('No file sent.');
    case UPLOAD_ERR_INI_SIZE:
        throw new RuntimeException('File exceeds upload_max_filesize directive in php.ini.');
    case UPLOAD_ERR_FORM_SIZE:
        throw new RuntimeException('File exceeds MAX_FILE_SIZE directive that was specified in the HTML form.');
    case UPLOAD_ERR_PARTIAL:
        throw new RuntimeException('File was only partially uploaded.');
    case UPLOAD_ERR_NO_TMP_DIR:
        throw new RuntimeException('Missing a temporary folder.');
    case UPLOAD_ERR_CANT_WRITE:
        throw new RuntimeException('Failed to write file to disk.');
    case UPLOAD_ERR_EXTENSION:
        throw new RuntimeException('File upload stopped by extension.');
    default:
        throw new RuntimeException('Unknown upload error.');
}

这样只要上传过程中出现任何错误,都会提前抛出对应异常,不会走到后面的格式校验步骤。

2. 新增临时文件存在性校验

保险起见,在调用finfo->file()之前,先确认临时文件确实存在,避免意外情况导致路径无效:

$tmpFilePath = $_FILES['fileToUpload']['tmp_name'];
if (!file_exists($tmpFilePath) || !is_file($tmpFilePath)) {
    throw new RuntimeException('Temporary upload file is missing.');
}

$finfo = new finfo(FILEINFO_MIME_TYPE);
if (false === $ext = array_search(
    $finfo->file($tmpFilePath),
    array(
        'jpg' => 'image/jpeg',
        'png' => 'image/png',
        'gif' => 'image/gif',
    ),
    true
)) {
    throw new RuntimeException('Invalid file format.');
}

3. 确认uploads目录权限

虽然当前错误不是移动文件导致,但提前确保./uploads目录存在且PHP有写入权限:

  • 在项目根目录手动创建uploads文件夹
  • 给它设置755权限(WAMP环境下确保Apache进程能写入)

修改后的完整PHP代码示例

<?php
header('Content-Type: text/plain; charset=utf-8');

function StartPy(){
    $command_exec = escapeshellcmd('A:\OCR EXPERIMENT\main.py');
    $str_output = shell_exec($command_exec);
    echo $str_output;
}

try {
    // Undefined | Multiple Files | $_FILES Corruption Attack
    // If this request falls under any of them, treat it invalid.
    if ( !isset($_FILES['fileToUpload']['error']) || is_array($_FILES['fileToUpload']['error']) ) {
        throw new RuntimeException('Invalid parameters.');
    }

    // Check $_FILES['fileToUpload']['error'] value.
    switch ($_FILES['fileToUpload']['error']) {
        case UPLOAD_ERR_OK:
            break;
        case UPLOAD_ERR_NO_FILE:
            throw new RuntimeException('No file sent.');
        case UPLOAD_ERR_INI_SIZE:
            throw new RuntimeException('File exceeds upload_max_filesize directive in php.ini.');
        case UPLOAD_ERR_FORM_SIZE:
            throw new RuntimeException('File exceeds MAX_FILE_SIZE directive that was specified in the HTML form.');
        case UPLOAD_ERR_PARTIAL:
            throw new RuntimeException('File was only partially uploaded.');
        case UPLOAD_ERR_NO_TMP_DIR:
            throw new RuntimeException('Missing a temporary folder.');
        case UPLOAD_ERR_CANT_WRITE:
            throw new RuntimeException('Failed to write file to disk.');
        case UPLOAD_ERR_EXTENSION:
            throw new RuntimeException('File upload stopped by extension.');
        default:
            throw new RuntimeException('Unknown upload error.');
    }

    // DO NOT TRUST $_FILES['fileToUpload']['mime'] VALUE !!
    // Check MIME Type by yourself.
    $tmpFilePath = $_FILES['fileToUpload']['tmp_name'];
    if (!file_exists($tmpFilePath) || !is_file($tmpFilePath)) {
        throw new RuntimeException('Temporary upload file is missing.');
    }

    $finfo = new finfo(FILEINFO_MIME_TYPE);
    if (false === $ext = array_search(
        $finfo->file($tmpFilePath),
        array(
            'jpg' => 'image/jpeg',
            'png' => 'image/png',
            'gif' => 'image/gif',
        ),
        true
    )) {
        throw new RuntimeException('Invalid file format.');
    }

    // You should name it uniquely.
    // DO NOT USE $_FILES['fileToUpload']['name'] WITHOUT ANY VALIDATION !!
    // On this example, obtain safe unique name from its binary data.
    $targetPath = sprintf('./uploads/%s.%s', sha1_file($tmpFilePath), $ext);
    if (!move_uploaded_file($tmpFilePath, $targetPath)) {
        throw new RuntimeException('Failed to move uploaded file.');
    }

    echo "File is uploaded successfully. \n";
    echo "Running Python Backend now!";
    StartPy();

} catch (RuntimeException $e) {
    echo $e->getMessage();
}
?>

额外排查点

  • 检查php.ini中的upload_max_filesize和post_max_size设置,确保上传文件大小不超过限制
  • 确认WAMP的Apache进程对系统临时目录有读写权限

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 16:42:34