davids_media Posted May 2, 2012 Share Posted May 2, 2012 I have some code where i input data and upload images to a database (working 100% correctly) However I want to expand on it - what I want is when a user uploads an image of their choice, to assign it to a directory of their choosing. Then, when input is successful, write the directory of where the image is stored (not just the image) to the database. Here is the code; <?php ini_set('display_errors',1); error_reporting(-1); require_once ('./includes/config.inc.php'); require_once (MYSQL); $add_cat_errors = array(); if ($_SERVER['REQUEST_METHOD'] == 'POST') { // Check for a name: if (empty($_POST['product'])) { $add_cat_errors['product'] = 'Please enter the name!'; } // Check for a description: if (empty($_POST['prod_descr'])) { $add_cat_errors['prod_descr'] = 'Please enter the description!'; } // Check for a category: if (!isset($_POST['cat']) || !filter_var($_POST['cat'], FILTER_VALIDATE_INT, array('min_range' => 1))) { $add_product_errors['cat'] = 'Please select a category!'; } // Check for a price: if (empty($_POST['price']) || !filter_var($_POST['price'], FILTER_VALIDATE_FLOAT) || ($_POST['price'] <= 0)) { $add_cat_errors['price'] = 'Please enter a valid price!'; } // Check for an image: if (is_uploaded_file ($_FILES['image']['tmp_name']) && ($_FILES['image']['error'] == UPLOAD_ERR_OK)) { $file = $_FILES['image']; $size = ROUND($file['size']/1024); // Validate the file size: if ($size > 512) { $add_cat_errors['image'] = 'The uploaded file was too large.'; } // Validate the file type: $allowed_mime = array ('image/jpeg', 'image/JPG', 'image/jpg'); $allowed_extensions = array ('.jpg', 'jpeg'); $image_info = getimagesize($file['tmp_name']); $ext = substr($file['name'], -4); if ( (!in_array($file['type'], $allowed_mime)) || (!in_array($image_info['mime'], $allowed_mime) ) || (!in_array($ext, $allowed_extensions) ) ) { $add_cat_errors['image'] = 'The uploaded file was not of the proper type.'; } // Move the file over, if no problems: if (!array_key_exists('image', $add_cat_errors)) { // Create a new name for the file: $new_name = (string) sha1($file['name'] . uniqid('',true)); // Add the extension: $new_name .= ((substr($ext, 0, 1) != '.') ? ".{$ext}" : $ext); // Move the file to its proper folder but add _tmp, just in case: $dest = "../db/images/$new_name"; if (move_uploaded_file($file['tmp_name'], $dest)) { // Store the data in the session for later use: $_SESSION['image']['new_name'] = $new_name; $_SESSION['image']['file_name'] = $file['name']; // Print a message: echo '<h4>The file has been uploaded!</h4>'; } else { trigger_error('The file could not be moved.'); unlink ($file['tmp_name']); } } // End of array_key_exists() IF. } elseif (!isset($_SESSION['image'])) { // No current or previous uploaded file. switch ($_FILES['image']['error']) { case 1: case 2: $add_cat_errors['image'] = 'The uploaded file was too large.'; break; case 3: $add_cat_errors['image'] = 'The file was only partially uploaded.'; break; case 6: case 7: case 8: $add_cat_errors['image'] = 'The file could not be uploaded due to a system error.'; break; case 4: default: $add_cat_errors['image'] = 'No file was uploaded.'; break; } // End of SWITCH. } // End of $_FILES IF-ELSEIF-ELSE. // Check for a stock: if (empty($_POST['stock']) || !filter_var($_POST['stock'], FILTER_VALIDATE_INT, array('min_range' => 1))) { $add_cat_errors['stock'] = 'Please enter the quantity in stock!'; } if (empty($add_cat_errors)) { $query = "INSERT INTO product (product, prod_descr, catID, price, image, stock) VALUES (?, ?, ?, ?, ?, ?)"; // Prepare the statement: $stmt = mysqli_prepare($dbc, $query); // For debugging purposes: // if (!$stmt) echo mysqli_stmt_error($stmt); // Bind the variables: mysqli_stmt_bind_param($stmt, 'sssssi', $name, $desc, $_POST['cat'], $_POST['price'], $_SESSION['image']['new_name'], $_POST['stock']); // Make the extra variable associations: $name = strip_tags($_POST['product']); $desc = strip_tags($_POST['prod_descr']); // Execute the query: mysqli_stmt_execute($stmt); if (mysqli_stmt_affected_rows($stmt) == 1) { // If it ran OK. // Print a message: echo '<h4>The product has been added!</h4>'; // Clear $_POST: $_POST = array(); // Clear $_FILES: $_FILES = array(); // Clear $file and $_SESSION['image']: unset($file, $_SESSION['image']); } else { // If it did not run OK. trigger_error('The product could not be added due to a system error. We apologize for any inconvenience.'); unlink ($dest); } } // End of $errors IF. } else { // Clear out the session on a GET request: unset($_SESSION['image']); } // End of the submission IF. require_once ('./includes/form_functions.inc.php'); ?> <form enctype="multipart/form-data" action="add_product.php" method="post" accept-charset="utf-8"> <input type="hidden" name="MAX_FILE_SIZE" value="524288" /> Product<br /><?php create_form_input('product', 'text', $add_cat_errors); ?> Description<br /><?php create_form_input('prod_descr', 'textarea', $add_cat_errors); ?> Category<br /><select name="cat"<?php if (array_key_exists('cat', $add_cat_errors)); ?>> <option>Select One</option> <?php // Retrieve all the categories and add to the pull-down menu: $q = 'SELECT catID, cat FROM category ORDER BY cat ASC'; $r = mysqli_query ($dbc, $q); while ($row = mysqli_fetch_array ($r, MYSQLI_NUM)) { echo "<option value=\"$row[0]\""; // Check for stickyness: if (isset($_POST['cat']) && ($_POST['cat'] == $row[0]) ) echo ' selected="selected"'; echo ">$row[1]</option>\n"; } ?> </select><?php if (array_key_exists('cat', $add_cat_errors)) echo $add_product_errors['cat']; ?> Price<br /><?php create_form_input('price', 'text', $add_cat_errors); ?> Image<br /><?php // Check for an error: if (array_key_exists('image', $add_cat_errors)) { echo $add_cat_errors['image'] . '<br /><input type="file" name="image"/>'; } else { // No error. echo '<input type="file" name="image" />'; // If the file exists (from a previous form submission but there were other errors), // store the file info in a session and note its existence: if (isset($_SESSION['image'])) { echo "<br />Currently '{$_SESSION['image']['file_name']}'"; } } // end of errors IF-ELSE. ?> <br /> <select name="select"> <option value="full_heads">db/images/full_heads</option> <option value="human_hair">db/images/human_hair</option> </select> Stock<br /><?php create_form_input('stock', 'text', $add_cat_errors); ?> <input type="submit" value="Add This Product" class="button" /> </fieldset> </form> How do I achieve this? Quote Link to comment https://forums.phpfreaks.com/topic/261974-file-upload-choose-a-directory-from-list-in-drop-down-menu/ Share on other sites More sharing options...
Mahngiel Posted May 3, 2012 Share Posted May 3, 2012 i would create an array of the folder names that permit uploading, then loop through that in a option group. then catch it on the post. Quote Link to comment https://forums.phpfreaks.com/topic/261974-file-upload-choose-a-directory-from-list-in-drop-down-menu/#findComment-1342488 Share on other sites More sharing options...
xyph Posted May 3, 2012 Share Posted May 3, 2012 It's also important to verify that the post data actually contains one of those array values though. Don't want users defining their own folders to upload to. Quote Link to comment https://forums.phpfreaks.com/topic/261974-file-upload-choose-a-directory-from-list-in-drop-down-menu/#findComment-1342492 Share on other sites More sharing options...
davids_media Posted May 3, 2012 Author Share Posted May 3, 2012 I have applied this glob_onlydir facility into my code, inside my form <select name="myDirs"> <option value="" selected="selected">Select a folder</option> <?php $dirs = glob("../db/images/*", GLOB_ONLYDIR); foreach($dirs as $val){ echo '<option value="'.$val.'">'.$val."</option>\n"; } ?> </select> it reads all of the directories, based on those I have chosen inside the images directory, however, is it possible to workaround this with my code to insert it alongside when I upload image or should i go down the route of using an array and looping through there, if so, how can I achieve this please? Quote Link to comment https://forums.phpfreaks.com/topic/261974-file-upload-choose-a-directory-from-list-in-drop-down-menu/#findComment-1342633 Share on other sites More sharing options...
Mahngiel Posted May 3, 2012 Share Posted May 3, 2012 The foreach is fine for creating the option group. Just catch $_POST['myDirs'], ensure it's what it's supposed to be, and alter your destination path after the image has been verified. Quote Link to comment https://forums.phpfreaks.com/topic/261974-file-upload-choose-a-directory-from-list-in-drop-down-menu/#findComment-1342656 Share on other sites More sharing options...
davids_media Posted May 3, 2012 Author Share Posted May 3, 2012 i'm really confused as to where to embed the $_POST['myDirs'], I did try and include it in some form to this bit of the code but to no avail $dest = "../db/images/$new_name"; Quote Link to comment https://forums.phpfreaks.com/topic/261974-file-upload-choose-a-directory-from-list-in-drop-down-menu/#findComment-1342670 Share on other sites More sharing options...
Mahngiel Posted May 3, 2012 Share Posted May 3, 2012 First thing you need is your folder listing. I don't recommend scanning a directory for the folder names, because it's not as safe as you should be. Let's say the directory structure of `db/images/` has three folders you want to permit uploads to: avatars, icons, wallpapers. Create a simple array and loop through it. $dirs = array('avatars', 'icons', 'wallpapers'); Your foreach is going create <option value="dir">dir_name</option>, which is going to be $_POSTed along with the image. On the script that receives the form to be processed, you'll need to prepare the collection of the dir_name. 1) you'll want to verify the upload directory submitted by the form is a folder that's actually permitted. 2) you'll want to add that name into the database so all your calls are congruent, and $_POST['myDirs'] should contain the string value of a folder name that you have permitted, just cross check the value of that with $dirs with `in_array` or what-have-you. Once that passes, you can prep for db and folder inserts: $new_name = $dir . '/' . $new_name; $dest = "../db/images" $new_name; Quote Link to comment https://forums.phpfreaks.com/topic/261974-file-upload-choose-a-directory-from-list-in-drop-down-menu/#findComment-1342675 Share on other sites More sharing options...
davids_media Posted May 3, 2012 Author Share Posted May 3, 2012 I am still confused, should I just have the $_POST("myDirs") with an IF statement applied at the beginning and where should my array list of directories go? Also On the script that receives the form to be processed, you'll need to prepare the collection of the dir_name. 1) you'll want to verify the upload directory submitted by the form is a folder that's actually permitted. 2) you'll want to add that name into the database so all your calls are congruent, and when should I verify the upload directory? Quote Link to comment https://forums.phpfreaks.com/topic/261974-file-upload-choose-a-directory-from-list-in-drop-down-menu/#findComment-1342703 Share on other sites More sharing options...
Mahngiel Posted May 3, 2012 Share Posted May 3, 2012 I am still confused, should I just have the $_POST("myDirs") with an IF statement applied at the beginning and where should my array list of directories go? Where you put it is up to you. It can be the first thing you do, or the last. PHP (and programming in general) is a puzzle for you to create with your own imagination. I'm not going to write you any code, but I'll show you some thought processes to figure it out for yourself. Also when should I verify the upload directory? It would seem logical to me that you would want to verify the folder before you processed the file. Quote Link to comment https://forums.phpfreaks.com/topic/261974-file-upload-choose-a-directory-from-list-in-drop-down-menu/#findComment-1342707 Share on other sites More sharing options...
xyph Posted May 3, 2012 Share Posted May 3, 2012 You've got it on the right track here Mahngiel, just a couple things I wanted to add. Unless your file system is compromised, or you use a user-defined variable for the path, scanning the path is a great way to get a list of allowed directories. It's not unsafe at all, unless there are directories in that path you might not want images in... smart design will help avoid that. The nice part about this is if you ever want to add a folder, the script will reflect the changes as soon as the directory is made. There's no need to change the 'allowed directories' in two different places now. The down side is you lose a little flexibility, like if you wanted to have a description in the select box, rather than just the folder name. $dirs = array( 'avatars' => 'Avatars and Other Small Images', 'wallpapers_light' => 'Light-coloured Wallpapers', 'wallpapers_dark' => 'Dark-coloured Wallpapers' ); You could use a database of sorts to store each folders description, but it seems a little overkill for a small project like this. Still worth mentioning though. Quote Link to comment https://forums.phpfreaks.com/topic/261974-file-upload-choose-a-directory-from-list-in-drop-down-menu/#findComment-1342736 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.