0

I am working on a form which allows users upload text, location and 4 multiple images for a project, I have successfully written a code that uploads form data into my database but the problem I do face is that whenever I upload more than 1 image with this form, the form text and location input are been inserted into my database more than 1 times (to match the number of images I have uploaded). For example I Uploaded 3 images using the form and text "Hello World" and location "NY", output should be;

  • Hello World
  • NY
  • [image 1] [image 2] [image 3]

But instead output is

  • Hello World NY

  • Hello World NY

  • Hello World NY
  • [image 1] [image 2] [image 3]

I will like to stop the duplicate of the form text to match the number of images uploaded using the form for I have tried removing my query from the foreach statement but get no result after upload. Below is my code

<?php  
    // start session
    session_start();

    // db
    include db.php";

    // random_char
    include "random_char.php";

    // compress image
    include "compress_image.php";

    // from user id
    $id = $_SESSION["id"];
    $user = $_SESSION["name"];

    if ($_SERVER["REQUEST_METHOD"] == "POST") {

        // post validations
        if (empty(trim($_POST['photo_post_box']))) {
            // $post_box = null; // post box
            $post_box_error = true; // post box is empty
        } elseif (strlen($_POST['photo_post_box']) > 500) {
            $post_box_error = true; // characters is greater than 500
        } else {
            $post_box = $_POST['photo_post_box'];
            $post_box_error = false;
        }

        // location validation
        if (empty(trim($_POST['photo_location']))) {
            $location = ""; // location
            $location_error = false; // location is empty
        } elseif (strlen(preg_replace('/[^a-zA-Z]/m', '', $_POST["photo_location"])) < 2) {
            $location_error = true; // location is less than 2
        } elseif (strlen(preg_replace('/[^a-zA-Z]/m', '', $_POST["photo_location"])) > 20) {
            $location_error = true; // location is greater than 20
        } elseif (!preg_match("/^[A-Za-z-,\s]+$/ ", $_POST["photo_location"])) {
            $location_error = true; // location has unwanted characters
        } else {
            $location = trim($_POST['photo_location']); // location
            $location_error = false;
        }

        // image validations
        $accepted_extensions = array(
            "gif",
            "png",
            "jpg",
            "jpeg"
        ); // extensions

        $img = $_FILES["img"]; // images

        foreach($img['name'] as $key => $name) {

            $files = $_FILES['img'];

            $img_extension = pathinfo($files["name"][$key], PATHINFO_EXTENSION); // image extention
            $img_extension = strtolower($img_extension); // image extension

            if (!file_exists($files['tmp_name'][$key])) {
                $img_error = true;
            } elseif (!in_array($img_extension, $accepted_extensions)) {
                echo "<font color='red'>Invalid format</font>";
                $img_error = true;
            } elseif ($files["size"][$key] > 10485760) {
                $img_error = true; // image is larger than 10mb
            } else {
                $img_error = false;
            }

            if ($post_box_error == false && $location_error == false && $img_error == false) {
                $time = md5(microtime()); // micro time hashed with md5
                $name_file = $project_name.".com(@".$user.")_".$time.$id; // rename image
                $ext = substr($name, strrpos($name, '.') + 1); // extension
                $uploaded_img = $name_file.'.'.$ext; // uploaded image
                $save_to_dir = __DIR__."/../../img/".$uploaded_img; // save image to directory
                $post_id = random_alphanumeric_string(8).'b'.$id; // post id

                // `users_post`
                $insert = "INSERT INTO users_post(post_id, by_user_id, post, post_location, date_n_time) VALUES(?, ?, ?, ?, NOW())";
                $stmt = mysqli_prepare($db, $insert);
                mysqli_stmt_bind_param($stmt, "siss", $post_id, $id, $post_box, $location);
                mysqli_stmt_execute($stmt);

                // `users_post_images`
                $insert = "INSERT INTO users_post_images(post_id, image) VALUES(?, ?)";
                $stmt = mysqli_prepare($db, $insert);
                mysqli_stmt_bind_param($stmt, "ss", $post_id, $uploaded_img);
                mysqli_stmt_execute($stmt);

                // compress and save uploaded image in directory
                compressImage($files['tmp_name'][$key], $save_to_dir, 60);
            }
            // close statement
            mysqli_stmt_close($stmt);   
        }   
    }
    // close db connection
    mysqli_close($db);
?> 

<form id="photo_post_box" method="POST" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" name="post_box" enctype="multipart/form-data" accept-charset="utf-8">
    <textarea class="form-control" name="photo_post_box" placeholder="Write something..."></textarea>
    <div class="mt-1">
        <input class="form-control" type="text" name="photo_location" placeholder="City, State">
    </div>
    <div class="mt-1">
        <input type="file" name="img[]" id="img1" accept=".gif, .jpg, .png" required="required">
        <input type="file" name="img[]" id="img2" accept=".gif, .jpg, .png">
        <input type="file" name="img[]" id="img3" accept=".gif, .jpg, .png">
        <input type="file" name="img[]" id="img4" accept=".gif, .jpg, .png">
    </div>
    <div class="mt-1">
        <button name="upload">
            <b>Upload</b>
        </button>
    </div>
</form> 
3
  • That’s because within the loop for images you also save form data. Commented Feb 25, 2020 at 23:09
  • But when I remove form data within loop, the form text and images are not been inserted into my database nor does the images uploaded stored into directory @DanielProtopopov Commented Feb 25, 2020 at 23:11
  • Does this answer your question? Uploading multiple images with one input field Commented Feb 26, 2020 at 3:54

1 Answer 1

1

Without going into code in great detail, here is generally what you are doing wrong and how you should do it.

The global $_FILES will contain all the uploaded file information. Its contents from the example form is as follows.

Array
(
[img] => Array
    (
        [name] => Array
            (
                [0] => bears.jpeg
                [1] => big cat.jpeg
                [2] => butterfly2.jpeg
                [3] => chipmunk.jpeg
            )

        [type] => Array
            (
                [0] => image/jpeg
                [1] => image/jpeg
                [2] => image/jpeg
                [3] => image/jpeg
            )

        [tmp_name] => Array
            (
                [0] => /tmp/phpNKGKa2
                [1] => /tmp/phpOCopiT
                [2] => /tmp/phphEGfqK
                [3] => /tmp/phpguKfyB
            )

        [error] => Array
            (
                [0] => 0
                [1] => 0
                [2] => 0
                [3] => 0
            )

        [size] => Array
            (
                [0] => 162804
                [1] => 133032
                [2] => 118203
                [3] => 164941
            )

    )

)

When you upload files, on the PHP side you will get a structure something like this:

So you have to walk through this structure to get all the files. The form data on the other hand is only stored once in $_POST.

So you must insert the form data once and the files you must use a loop to go through them all.

// INSERT form data first outside the loop

// Then go through the files in a loop
foreach ($_FILES["img"]["error"] as $key => $error) {
    if ($error == UPLOAD_ERR_OK) {
        // INSERT file here
        $tmp_name = $_FILES["pictures"]["tmp_name"][$key];
        $name = basename($_FILES["pictures"]["name"][$key]);
        // Usually you have to do this
        move_uploaded_file($tmp_name, "some/real/dir");
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.