Jump to content

file upload - choose a directory from list in drop down menu


davids_media

Recommended Posts

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?

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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;

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.