Search code examples
phpunlink

File continues to exist after deletion with unlink()


I'm creating an edit-profile PHP page where a user can change his profile picture.

Initially, the page displays the original picture, but the picture should update immediately once a new picture has been chosen and the submit button has been pressed. When the submit button is pressed, I use unlink() to remove the original file and then move_uploaded_file() to put the new picture in the folder.

While the original picture is deleted and I can see the new one has been moved to the folder, it still tells me that the original folder exists and doesn't show me the new picture. Instead, I just get the little thumbnail image that tells me there was no file at the specified URL. If I print the $uploaded_files variable upon submit, it gives me the original picture even though it has been deleted.

What is weird is when I choose the picture a second time it works. [enter link description here][1]

I tried using the clearstatcache() after unlink() but that didn't do anything. Below is my code. Please help. If it helps, here is a link to a video of what is happening with the code: https://youtu.be/kZMDykuVVKo

<form method='post' action='edit-profile.php' enctype="multipart/form-data">
<input type="hidden" name="MAX_FILE_SIZE" value="200000">
<p><label for="upload">Select a new profile picture:</label><br> <input type="file" name="picture"></p>

<?php 
$uploaded_files = scandir('users/someUser/profilePicture');
$path = 'users/someUser/profilePicture';
for($i=0; $i<count($uploaded_files); $i++) {
    if(is_file("$path/{$uploaded_files[$i]}")) {
        print "<img src='users/someUser/profilePicture/{$uploaded_files[$i]}'><br>";
    }
}

print '<input type="submit" name="profile_picture_submit" value="Change Picture" class="button--pill">
</form>';  

if (isset($_POST['profile_picture_submit'])) {
    unlink('users/someUser/profilePicture/'. $uploaded_files[2]);

    $file_ext = explode('.', $_FILES['picture']['name']);
    $file_ext = strtolower(end($file_ext));
    $allowed = array('png', 'jpg');

    if(in_array($file_ext, $allowed)) {
        if(move_uploaded_file($_FILES['picture']['tmp_name'], "users/someUser/profilePicture/{$_FILES['picture']['name']}")) {
            echo "Your file has been uploaded";
        }
        else {
            echo "There was a problem uploading the file"; 
        }
    }
    else {
        print "<p class='error'>Type $file_ext is not allowed.</p>";
    }
}

Solution

  • Step through what is happening. Let's imagine the code running as you visit the page in the browser the first time:

    1. The first part of the code displays a form, and the current pic.

    2. Nothing was POSTed yet, so the image processing part of the code doesn't run. The code is finished, the page is done, user is left looking at the current image, and the form. All done for this page load.

    3. Now the user adds a new photo, and clicks submit. This POSTs to your PHP. This means a new page is requested and the code will display it in the browser.

    4. The first thing that happens - the top part of the code - is that the code shows the form, and the current image. No image processing has happened yet. We've just POSTed a new image, but nothing has been done with it yet, so that display code at the top just shows the old pic that is still on disk.

    5. Now, processing continues to the test to see if an image was POSTed. It was, so the image processing section runs - your old image is removed and the new image moved into place.

    6. Now processing is done, and everything stops. The user is left looking at the form and the old picture that was displayed in step 4, even though it has now been deleted, and a new one added.

    To see the new image, you'd need to reload the page. Try it - but don't just hit reload because that will POST again - click in the browser's URL bar, and hit enter, or copy the URL and try in a new tab, to load the page with GET. You'll see your new image.

    Of course you will also see your new image if you repeat the process of adding a new image, as you do in your video, because this time the new image is the one on disk.

    So how to solve it? You really just need to switch the order of processing of your 2 sections:

    // First check if an image was uploaded, and do that processing if so
    if (isset($_POST['profile_picture_submit'])) {
        // ... your code ...
    }
    
    <!-- Now images have been handled, display whatever is on disk -->
    <form method='post' action='edit-profile.php' enctype="multipart/form-data">
        // ... your code ...
    </form>