首页 > 解决方案 > PHP通过循环上传多个图像

问题描述

我正在尝试循环上传多个图像,但由于某种原因,它会创建目录,上传 1 个文件并创建 MySQL 记录,所以我不确定为什么它只上传 1 个文件,即使我已经打印 $i 到看看有多少文件被计算在内,它总是计算正确的数量。

PHP

function generateRandomString($length = 25) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
}
if (isset($_POST['newYoungSubmit'])) {

    $imageDirectory = "images/youngMembers";
    $newDirName = generateRandomString(20);
    $postDate = date("Y-m-d");
    $targetDir = $imageDirectory."/".$newDirName."/";

    if (!file_exists($targetDir)) {
        mkdir($targetDir, 0777, true);
    } else {
        $newDirName = generateRandomString(20);
        $targetDir = $imageDirectory."/".$newDirName."/";
    }

    // Count total files
    $fileCount = count($_FILES['new_young']['name']);
    // Iterate through the files
    for($i = 0; $i < $fileCount; $i++){
        $target_dir = $imageDirectory."/".$newDirName."/";
        $target_file = $target_dir . basename($_FILES["new_young"]["name"][$i]);
        $uploadOk = 1;
        $imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
        // Check if image file is a actual image or fake image
        $check = getimagesize($_FILES["new_young"]["tmp_name"][$i]);
        if($check !== false) {
            //echo "File is an image - " . $check["mime"] . ".";
            $uploadOk = 1;
        } else {
            $errorTxt = "File is not an image.";
            $uploadOk = 0;
        }
        // Check if file already exists
        if (file_exists($target_file)) {
            $errorTxt =  "Sorry, file already exists.";
            $uploadOk = 0;
        }
        // Check file size
        // if ($_FILES["new_young"]["size"] > 500000) {
        //     $errorTxt =  "Sorry, your file is too large.";
        //     $uploadOk = 0;
        // }
        // Allow certain file formats
        if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
        && $imageFileType != "gif" ) {
            $errorTxt = "Sorry, only JPG, JPEG, PNG & GIF files are allowed.";
            $uploadOk = 0;
        }
        // Check if $uploadOk is set to 0 by an error
        $temp = explode(".", $_FILES["new_young"]["name"][$i]);
        $newfilename = round(microtime(true)) . '.' . end($temp);
        if ($uploadOk == 0) {
            
        // if everything is ok, try to upload file

        } else {
            if (move_uploaded_file($_FILES["new_young"]["tmp_name"][$i], $target_dir . $newfilename)) {
                //echo "The file ". basename( $_FILES["new_young"]["name"]). " has been uploaded.";
            } else {
                $errorTxt = "Sorry, there was an error uploading your file.";
            }
        }
    }

    $newYoungQuery = $conn->prepare("INSERT INTO youngMembers (youngTitle, youngImgDir, youngDesc) VALUES (?,?,?)");
    $newYoungQuery->execute([$_POST['youngTitle'], $targetDir, $_POST['youngDesc']]);
    $newYoungQuery = null;

    }

HTML

<form class="col s12" method="POST" action="" enctype="multipart/form-data">
    <div class="row">
        <div class="input-field col s12 m6">
            <input name="youngTitle" id="youngTitle" required type="text" class="validate">
            <label for="youngTitle">Title<span class="red-text">*</span></label>
        </div>
        <div class="file-field input-field col s12 m6">
            <div class="btn">
                <span>Image(s)</span>
                <input name="new_young[]" type="file" multiple="multiple">
            </div>
            <div class="file-path-wrapper">
                <input class="file-path validate" type="text">
            </div>
        </div>
    </div>
    <div class="row">
        <div class="input-field col s12 m12">
            <div class="input-field col s12 m12">
                <textarea id="youngDesc" name="youngDesc" class="materialize-textarea" data-length="4096"></textarea>
                <label for="youngDesc">Description</label>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col s12 m3 offset-m9 input-field">
            <input type="submit" class="white green-button-border black-text btn-large" name="newYoungSubmit">
        </div>
    </div>
</form>

我已经上传了 HTML 表单和提交表单时运行的 PHP 脚本,据我所知,我的脚本将检查表单是否已提交,生成一个随机字符串,该字符串成为新的目录名称,之后我检查了它是否已创建,如果没有创建新目录,然后我运行一个循环循环遍历并将所有选定的图像上传到该目录,最后我将数据上传到 MySQL 表。

标签: phphtmlimage-processingfile-upload

解决方案


问题,我相信正确地检查了代码并对其进行了测试,因为文件正在以新名称保存并且新名称是使用以下命令生成的:

$newfilename = round( microtime(true) ) . '.' . end($temp);

当我在 3 个文件上传上对此进行测试时,我在添加一些调试语句时观察到以下情况。

..OK
1630745144.jpg - OK

..OK
1630745144.jpg - OK

..OK
1630745144.jpg - OK

所有三个都分配了相同的名称,因此只有最后一个似乎已上传,而其他两个已被覆盖。

提到的调试是:

$newfilename = round( microtime(true) ) . '.' . end($temp);
if ($uploadOk == 0) {
    echo $errorTxt;
} else {
    
    if (move_uploaded_file($_FILES["new_young"]["tmp_name"][$i], $target_dir . $newfilename)) {
        echo '..OK<br />';
    } else {
        $errorTxt = "Sorry, there was an error uploading your file.";
    }
    echo $newfilename . ' - OK<br />';
}

有人会假设$errorTxt这里会声明文件已经存在,但事实并非如此,因为$target_file并且$newfilename不会相同。新名称应在if (file_exists($target_file)) {检查之前生成。

所以 - 如果您将原始代码中的相关代码更改为此逻辑测试将起作用,但文件仍将无法上传。

$temp = explode(".", $_FILES["new_young"]["name"][$i]);
$newfilename = round( microtime(true) ) . '.' . end($temp);
$target_file = $target_dir . $newfilename;

if (file_exists($target_file)) {
    $errorTxt =  "Sorry, file already exists.";
    $uploadOk = 0;
}



if ($uploadOk == 0) {
    // if everything is ok, try to upload file
    echo $errorTxt;
} else {
    
    if (move_uploaded_file($_FILES["new_young"]["tmp_name"][$i], $target_file )) {
        //echo "The file ". basename( $_FILES["new_young"]["name"]). " has been uploaded.";
    } else {
        $errorTxt = "Sorry, there was an error uploading your file.";
    }
}

现在的问题是这$newfilename = round( microtime(true) )将生成相同的整数 - 一个大整数但相同。从微时间派生的精度会丢失,因此您可以将其修改为:

$newfilename =  str_replace( '.', '', strval( microtime( true ) ) ) . '.' . end( $temp ); 

完成后,您的代码应该一切正常 - 三张图片上传正常。


推荐阅读