Page 1 of 1

Re: delete image from server folder and db table

Posted: Sun Jan 24, 2016 7:01 am
by requinix
The closest you got to looking for those checkboxes in code was

Code: Select all

$file_name = (isset($_POST['file_name']));
but that only tells you the form was submitted with at least one checked.
$_POST['file_name'] will be an array of file_name. You need an if in there to only do the deletion if the current filename (in $record) matches one of the items in that array.

Or better, (1) use IDs instead of filenames and (2) do your SELECT for only those IDs and not simply every image for the user. That implies two separate actions: one to delete whatever was sent with the form, another to display the deletable images. Which is a better course of action anyways, if you ask me.

Re: delete image from server folder and db table

Posted: Sun Jan 24, 2016 7:56 am
by Celauran
ianhaney wrote:would I need something like this for the if part

Code: Select all

if( is_uploaded_file($record['file_name']) )
With regard to deleting existing files? No.

Re: delete image from server folder and db table

Posted: Sun Jan 24, 2016 8:37 am
by Celauran
ianhaney wrote:and I get the following added to the url in the address bar
Did you forget to post something, maybe?

Re: delete image from server folder and db table

Posted: Sun Jan 24, 2016 8:48 am
by Celauran

Code: Select all

echo '<form>';
echo '<input name="file_name[]" type="checkbox" id="checkbox[]" value="<? echo $record; ?>"/>';
echo '<br>';
echo "<input name='delete' type=submit id='delete' value='Delete'>";
echo '</form>';
There are a number of problems with this form:
- you've got an echo statement nested inside an echo statement
- Short tags (<?) should not be used
- HTML element IDs should be unique
- $record is an array, so assigning it to the value of the checkbox won't work.

Moreover, when this form is submitted, $_POST will contain file_name (which is an array of... something. Won't work until you fix the value), and delete. That's it.

Code: Select all

         $sql = "DELETE FROM images WHERE image_id = :image_id";
         }     

$stmt = $db->prepare($sql);
$stmt->bindParam(':image_id', $_POST['image_id'], PDO::PARAM_INT);
$_POST['image_id'] is not set. There is no form field called image_id.

Code: Select all

unlink("user-images/".$record['file_name']);
Where is $record coming from?

Code: Select all

$file_name = (isset($_POST['file_name']));
This will evaluate to a boolean, though you don't appear to be using it anywhere.

Code: Select all

$array = array("checkbox" => $_POST['checkbox']);  //WOULD I NEED CHANGE THE CHECKBOX TO FILE_NAME ON THIS LINE
What is this meant to be doing?

Re: delete image from server folder and db table

Posted: Sun Jan 24, 2016 8:49 am
by Celauran
ianhaney wrote:ahh would that be method="post" in the form tag?
Well yes, I suppose. I meant more that you referenced a change in the URL bar, but never specified what said change was.

Re: delete image from server folder and db table

Posted: Sun Jan 24, 2016 10:51 am
by Celauran
I did a little cleanup of your code in trying to see where you were running into errors. Sounds like you've already got things sorted, so that's awesome. Going to post this here for reference anyway.

Code: Select all

<?php

// This should probably be moved to your config file so you don't need
// to explicitly call it on every page.
ini_set('display_startup_errors',1);
ini_set('display_errors',1);
error_reporting(-1);

// Defining a bunch of functions here. This helps keep the logic separate from
// the presentation of the page. Further, each function is relatively limited
// in scope; it does only one specific thing. If you later need to change some
// functionality, you can change it in a single location
function getMemberImages($db, $member_id)
{
    $query = "SELECT image_id, file_name FROM images WHERE memberID = :member_id";
    $stmt = $db->prepare($query);
    $exec = $stmt->execute(['member_id' => $member_id]);

    return $exec ? $stmt->fetchAll(PDO::FETCH_ASSOC) : [];
}

function getImageFileNames($db, $images)
{
    $file_names = [];

    $query = "SELECT file_name FROM images WHERE image_id = :image_id";
    $stmt = $db->prepare($query);
    foreach ($images as $image) {
        $exec = $stmt->execute(['image_id' => $image]);
        if ($exec) {
            $file_names[] = $stmt->fetchColumn();
        }
    }

    return $file_names;
}

function deleteImages($db, $base_dir, $images = array())
{
    $file_names = getImageFileNames($db, $images);
    deleteImagesFromDatabase($db, $images);
    deleteImagesFromFilesystem($base_dir, $file_names);
}

function deleteImagesFromDatabase($db, $images = array())
{
     $query = "DELETE FROM images WHERE image_id = :image_id";
     $stmt = $db->prepare($query);
     foreach ($images as $image) {
         $stmt->execute(['image_id' => $image]);
     }
}

function deleteImagesFromFilesystem($base_dir, $images = array())
{
    foreach ($images as $image) {
        if (file_exists($base_dir . $image)) {
            unlink($base_dir . $image);
        }
    }
}

function cleanFilesArray($files)
{
    $cleaned = [];
    foreach ($files['name'] as $key => $file) {
        $cleaned[$key] = [
            'name' => $files['name'][$key],
            'type' => $files['type'][$key],
            'size' => $files['size'][$key],
            'tmp_name' => $files['tmp_name'][$key],
            'error' => $files['error'][$key],
        ];
    }

    return $cleaned;
}

function handleFileSubmission($db, $member_id, $base_dir, $files = array())
{
    if (!is_dir($base_dir)) {
        $directory_created = mkdir($base_dir, 0700);
        // If the directory doesn't exist AND we're not able to create it, we bail
        if (!$directory_created) {
            return false;
        }
    }

    $status = [
        'files' => [],
        'errors' => [],
    ];

    $cleaned = cleanFilesArray($files);
    foreach ($cleaned as $file) {
        if ($file['error'] != UPLOAD_ERR_OK) {
            $status['errors'][] = "There was a problem uploading file: {$file['name']}";
            continue;
        }

        if ($file['size'] > 6097152){
            $status['errors'][] = 'File size must be less than 6 MB';
            continue;
        }

        $fs = saveImageToFilesystem($base_dir, $file);
        if ($fs) {
            $db = insertFileUploadToDatabase($db, $member_id, $fs, $file);
            if (!$db) {
                deleteImagesFromFilesystem($base_dir, [$fs]);
                $status['errors'][] = "File '{$file['name']}' could not be saved.";
            } else {
                $status['files'][] = $file['name'];
            }
        } else {
            $status['errors'][] = "File '{$file['name']}' could not be saved.";
        }
    }

    return $status;
}

function insertFileUploadToDatabase($db, $member_id, $filename, $file_array)
{
    $query = "INSERT INTO images (memberID, file_name, file_size, file_type)
              VALUES (:memberID, :file_name, :file_size, :file_type)";
    $stmt  = $db->prepare($query);
    $exec = $stmt->execute([
        'memberID' => $member_id,
        'file_name' => $filename,
        'file_size' => $file_array['size'],
        'file_type' => $file_array['type'],
    ]);

    return $exec;
}

function saveImageToFilesystem($base_dir, $file)
{
    $filename = $file['name'];
    if (file_exists($base_dir . $file['name'])) {
        $filename = $file['name'] . time();
    }

    $moved = move_uploaded_file($file['tmp_name'], $base_dir . $filename);

    return $moved ? $filename : false;
}

?>

<?php require('includes/config.php');

$memberID = $_SESSION["memberID"]; // store the user id into session

//if not logged in redirect to login page
if (!$user->is_logged_in()) { header('Location: login.php'); }

// the folder where the images are saved
$target = "user-images/";

// If the delete image form has been submitted and if images were selected,
// delete the records from the database and remove the images from the file system
if (isset($_POST['delete']) && !empty($_POST['image_id'])) {
    deleteImages($db, $target, $_POST['image_id']);
}

if (isset($_FILES['files'])) {
    $status = handleFileSubmission($db, $memberID, $target, $_FILES['files']);
}

//define page title
$title = 'Members Page';

// If we've made it this far, we know we have a logged in user.
// Let's retrieve their images for display on the page.
$user_images = getMemberImages($db, $memberID);

//include header template
require('layout/header.php');

// Everything below is concerned strictly with rendering the display.
// All the logic -- form processing and the like -- has been isolated above.

?>

<div class="container">
    <div class="row">
        <div class="col-xs-12 col-sm-8 col-md-6 col-sm-offset-2 col-md-offset-3">
            <h2>Member only page - Welcome <?php echo $_SESSION['username']; ?></h2>
            <hr />
            <?php if (isset($status) && !empty($status['errors'])): ?>
                <?php foreach ($status['errors'] as $error): ?>
                    <p><?= $error; ?></p>
                <?php endforeach; ?>
            <?php endif; ?>
            <form action="" method="POST" enctype="multipart/form-data">
                <input type="file" name="files[]" multiple/>
                <input type="submit" value="Upload Images"/>
            </form>
            <hr />
            <p><a href='logout.php'>Logout</a></p>
            <hr>
        </div>
    </div>
</div>

<h1>Your Images</h1>

<?php // We're going to wrap all of this in a form so we can delete multiple images with a single submission. ?>
<form action="" method="post">

    <?php // We defined $user_images when the page loaded. Now we can just display them. ?>
    <?php foreach ($user_images as $image): ?>
        <?php $photo = ($image['file_name'] == null) ? "me.png" : $image['file_name']; ?>
        <img src="<?= $target.$photo; ?>">
        <input type="checkbox" name="image_id[]" value="<?= $image['image_id']; ?>">
    <?php endforeach; ?>

    <input type="submit" name="delete" value="Delete Selected">
</form>

<hr />

<?php require('layout/footer.php'); ?>

Re: delete image from server folder and db table

Posted: Sun Jan 24, 2016 11:02 am
by Celauran

Code: Select all

if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
    echo "The file ".  basename( $_FILES['uploadedfile']['name']).
    " has been uploaded";
} else{
    echo "There was an error uploading the file, please try again!";
}
You aren't checking if $_FILES contains any values, so this bit is being run every time the page loads. When $_FILES is empty, move_uploaded_file returns false, error gets displayed.

Re: delete image from server folder and db table

Posted: Sun Jan 24, 2016 11:23 am
by Celauran
That sounds like more of a workaround than a proper fix. You still need to check the contents of $_FILES. Submit the form with no attached images and I expect you'll encounter the same error.