uploading images - having problems


#1

I’m trying to set the upload_tmp_dir directive so I can upload images within my script. I don’t have access to my hosts php.ini file and ini_set doesn’t work for upload_tmp_dir.

After asking around, no one seems to be able to know an alternative, or if there is one at all but there must be one surely.

How do I set my tmp directory without using php.ini?

Any help would be greatly apprecisted.

Cheers
M


#2

I’m not sure if you can, if ini_set() won’t allow it. For normal file upload, I don’t think you need to even be aware of upload_tmp_dir though. What did you have in mind with it?


#3

I just want to upload jpegs but do a few validation checks before it gets dumped into a secure directory.

To be honest, any alternative will do now as this problem is doin my head in.

Thanks
M


#4

Is there a particular reason that you don’t want to use the Host’s temp directory? The webserver should have the required read/write to allow for this unless the host is specifically blocking it.


#5

I’ve asked them and they are being a bit dumb on the subject.

Just ran a test script and got this error.

Array ( [file] => Array ( [name] => 00120032.jpg [type] => image/jpeg [tmp_name] => C:WINDOWSTEMPphp518.tmp [error] => 0 [size] => 10017 ) ) File has been successfully uploaded!

It says the file was uploaded, but it wasn’t in the directory I set in the code.

Cheers


#6

Perhaps this is silly, but did you do a copy FROM the temp dir (using the Temporary name) TO the intended folder using the intended name?

When you upload the files PHP will name it a temporary name in your case it looks like it was named php518.tmp

After uploaded you need to copy it from C:WINDOWSTEMPphp518.tmp to your intended folder as 00120032.jpg (or some other name as you decide).


#7

Ah, i don’t think so.

This is the test script i used:

[php]

<?php if ($HTTP_POST_VARS['submit']) { print_r($HTTP_POST_FILES); if (!is_uploaded_file($HTTP_POST_FILES['file']['tmp_name'])) { $error = "You did not upload a file!"; unlink($HTTP_POST_FILES['file']['tmp_name']); // assign error message, remove uploaded file, redisplay form. } else { //a file was uploaded $maxfilesize=20240; if ($HTTP_POST_FILES['file']['size'] > $maxfilesize) { $error = "file is too large"; unlink($HTTP_POST_FILES['file']['tmp_name']); // assign error message, remove uploaded file, redisplay form. } else { if ($HTTP_POST_FILES['file']['type'] != "image/gif" AND $HTTP_POST_FILES['file']['type'] != "image/jpeg") { $error = "This file type is not allowed"; unlink($HTTP_POST_FILES['file']['tmp_name']); // assign error message, remove uploaded file, redisplay form. } else { //File has passed all validation, copy it to the final destination and remove the temporary file: copy($HTTP_POST_FILES['file']['tmp_name'],"/images/".$HTTP_POST_FILES['file']['name']); unlink($HTTP_POST_FILES['file']['tmp_name']); print "File has been successfully uploaded!"; exit; } } } } ?> <?=$error?>

Choose a file to upload:

[/php]

ADMIN EDIT: Added [php] tags for readability. Please refer to http://phphelp.com/guidelines.php for posting guidelines.


#8

Is this server on a WINDOWS machine? If so you have to deal with the backslashes that Windows use (as unix uses them as the escape character)

I would be curious to see the output of the following :
[php]
echo ‘copy(’.$HTTP_POST_FILES[‘file’][‘tmp_name’].’,/images/’.$HTTP_POST_FILES[‘file’][‘name’].’)’;
[/php]

Just before the normal copy command in that script.


#9

Yes it is on a windows server.

Array ( [file] => Array ( [name] => 00120032.jpg [type] => image/jpeg [tmp_name] => C:WINDOWSTEMPphp774.tmp [error] => 0 [size] => 10017 ) ) copy(C:WINDOWSTEMPphp774.tmp,/images/00120032.jpg)File has been successfully uploaded!


#10

This is where it get’s interesting.

The copy command that gets sent to php is

[php]
copy(C:WINDOWSTEMPphp774.tmp,/images/00120032.jpg)
[/php]

However the backslashes are the “Escape” character for php. Thus the above is seen broken up because the W, T and p (escape W, escape T and escape p respectively) I am not sure if they are at all legitimate escape sequences, but nonetheless, it’s a problem. Therefore you would need to modify the copy command so that it’s more like this:

[php]
copy(C:\WINDOWS\TEMP\php774.tmp,/images/00120032.jpg)
[/php]
The that’s because to represent a literal backslash, it’s escape sequence is \ (escape backslash). I hope it makes sense.

Now you can do that a couple of ways, like using regular expresions. I just use str_replace.

[php]
$userfile = str_replace("","\", $userfile);
[/php]

Your next problem is that you trying to copy from a windows style folder C:WINDOWSTEMPphp774.tmp to a *nix style folder /images/00120032.jpg

I don’t believe that will work. You need to be consistent. Since you are on a “Windows” server, you destination should probably be more like c:\inetpub\wwwroot\MyDir\images\00120032.jpg or whatever the appropriate path for you is, but I think you can see my point.


#11

Also, be sure to check out this page: Handling File Uploads.

The fatal function I’m missing in your script is move_uploaded_file().


#12

This is what I have at the moment, and no it doesn’t work as expected.
Any pointers as to what I am doing wrong?

Cheers

[php]

<?php if ($HTTP_POST_VARS['submit']) { //print_r($HTTP_POST_FILES); if (!is_uploaded_file($HTTP_POST_FILES['Userfile']['tmp_name'])) { $error = "You did not upload a file!"; unlink($HTTP_POST_FILES['userfile']['tmp_name']); // assign error message, remove uploaded file, redisplay form. } else { //a file was uploaded $maxfilesize=20240; if ($HTTP_POST_FILES['userfile']['size'] > $maxfilesize) { $error = "file is too large"; unlink($HTTP_POST_FILES['userfile']['tmp_name']); // assign error message, remove uploaded file, redisplay form. } else { if ($HTTP_POST_FILES['userfile']['type'] != "image/gif" AND $HTTP_POST_FILES['file']['type'] != "image/jpeg") { $error = "This file type is not allowed"; unlink($HTTP_POST_FILES['userfile']['tmp_name']); // assign error message, remove uploaded file, redisplay form. } else { //File has passed all validation, copy it to the final destination and remove the temporary file: copy($HTTP_POST_FILES['userfile']['tmp_name'],"images/".$HTTP_POST_FILES['userfile']['name']); unlink($HTTP_POST_FILES['userfile']['tmp_name']); print "File has been successfully uploaded!"; exit; if(move_uploaded_file($HTTP_POST_FILES['userfile']['tmp_name'], "images/".$HTTP_POST_FILES['userfile']['name'])) { // add the name to the database $inssql = "INSERT INTO images(item_id, name) VALUES(" . $validid . ", '" . $HTTP_POST_FILES['userfile']['name'] . "')"; mysql_query($inssql); header("Location: " . $HOST_NAME . $SCRIPT_NAME . "?id=" . $validid); echo "File has been stored in your image directory."; } } else { echo 'There was a problem uploading your file.
'; } } } } else { require("header.php"); $imagessql = "SELECT * FROM images WHERE item_id = " . $validid . ";"; $imagesresult = mysql_query($imagessql); $imagesnumrows = mysql_num_rows($imagesresult); echo "

Current images

"; if($imagesnumrows == 0) { echo "No images."; } else { echo ""; while($imagesrow = mysql_fetch_assoc($imagesresult)) { echo ""; echo ""; echo ""; echo ""; } echo "
[delete]
"; } ?>
Image to upload

When you have finished adding photos, go and <a href="<?php echo "itemdetails.php?id=" . $validid; ?>">see your item!

<?php } ?>

[/php]


#13

[php]
copy($HTTP_POST_FILES[‘userfile’][‘tmp_name’],“images/”.$HTTP_POST_FILES[‘userfile’][‘name’]);
unlink($HTTP_POST_FILES[‘userfile’][‘tmp_name’]);
[/php]

I think this is the problem (or at least one of them).
I don’t know if it works or not, but I pointed out earlier to use move_uploaded_file() and to read up on Handling File Uploads, which explains perfectly how to build a working file upload form and script.

It gives much information about what happens to upload files that are temporarily stored (and that they’re destroyed automatically, so your unlink() action is unnecessary, and you’re misusing copy() (in the php manual it says that copy() requires the full (relative or absolute) path to a file, not just its name).

Also, use this on top of your pages:

[php]error_reporting(E_ALL);[/php]

to ensure validity and completeness of all your scripts.


#14

Really appreciate the help.

I’ve had a look on the php site and I am just getting a little confused.

Should I use $_files or $HTTP…etc?

Can’t change the php.ini file but does this matter?

I have move_uploaded_file after the copy function. Is this right or should I only be using one of them?

Cheers


#15

Whether to use $_FILES or $HTTP_POST_FILES depends on your PHP version (as explained on the Handling File Uploads page ;)). You won’t need ini_set() or copy() at all.


#16

Okay, I have done the following with move_upload_files.

Its still not working, suprisingly!

Is there anything in there that you think could cause a problem?

[php]
// validation checks

if($_POST[‘submit’])
{
if($_FILES[‘userfile’][‘name’] == ‘’)
{
header("Location: " . $HOST_NAME . $SCRIPT_NAME . “?error=nophoto”);
}
elseif($_FILES[‘userfile’][‘size’] == 0)
{
header("Location: " . $HOST_NAME . $SCRIPT_NAME . “?error=photoprob”);
}
elseif($_FILES[‘userfile’][‘size’] > $MAX_FILE_SIZE)
{
header("Location: " . $HOST_NAME . $SCRIPT_NAME . “?error=large”);
}
elseif(!getimagesize($_FILES[‘userfile’][‘tmp_name’]))
{
header("Location: " . $HOST_NAME . $SCRIPT_NAME . “?error=invalid”);
}
else
{
$uploaddir = “/images/”;
$uploadfile = $uploaddir . $_FILES[‘userfile’][‘name’];

   if(move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) 
   		{
		
		$inssql = "INSERT INTO images(item_id, name) VALUES(" . $validid . ", '" . $_FILES['userfile']['name'] . "')";
		mysql_query($inssql);
		
		header("Location: " . $HOST_NAME . $SCRIPT_NAME . "?id=" . $validid);
   		}
   else {
       	echo 'There was a problem uploading your file.<br />';
   		}
	} 	
}

else
{
require(“header.php”);

$imagessql = "SELECT * FROM images WHERE item_id = " . $validid . ";";
$imagesresult = mysql_query($imagessql);
$imagesnumrows = mysql_num_rows($imagesresult);

echo "<h1>Current images</h1>";

if($imagesnumrows == 0) 
	{
	echo "No images.";
	}
else 
	{
	echo "<table>";
	while($imagesrow = mysql_fetch_assoc($imagesresult)) 
		{
		echo "<tr>";
		echo "<td><img src='" . $config_basedir . "/images/" . $imagesrow['name'] . "' width='100'></td>";
		echo "<td>[<a href='deleteimage.php?image_id=" . $imagesrow['id'] . "&item_id=" . $validid . "'>delete</a>]</td>";
		echo "</tr>";
		}
	echo "</table>";
	}
	
switch($_GET['error']) 
	{
	case "empty":
		echo 'You did not select anything.';
	break;

	case "nophoto":
		echo 'You did not select a photo to upload.';
	break;

	case "photoprob":
		echo 'There appears to be a problem with the photo your are uploading';
	break;

	case "large":
		echo 'The photo you selected is too large';
	break;
	
	case "invalid":
		echo 'The photo you selected is not a valid image file';
	break;
	}

?>

Image to upload

When you have finished adding photos, go and <a href="<?php echo "itemdetails.php?id=" . $validid; ?>">see your item!

<?php } ?>

[/php]


#17

Now I don’t run PHP on a windows system I use linux so I may be wrong, HOWEVER, isn’t $uploaddir = “/images/”; Incorrect if you are running on a windows system?

Shouldn’t it be more like $uploaddir = “c:images”; and because of the “Escape” issue discussed earlier in this thread, it should probably be $uploaddir = “c:\images”;

Not to mention that you need to make sure the “Source” information is also correctly “escaped”.

If I am wrong on this, someone please correct me.


#18

I’m wondering if I might as well move over to a Linux server. I can get it done quickly.

I was gonna do this orignally but decided to stick to windows.

What do you think?

Cheers


#19

Personally, I have been EXTREMELY happy with my Linux box. It has been running like a ROCK for at least 5 years. (Dual Pentium III 933 Mhz, 2 GB RAM, 180 GB Raid 5, 1 hot spare, hot swappable). In fact that’s what’s running this software.

Although I have been “attacked” a couple of times, it’s far less than one would probably have been attacked with a windows.


#20

Might be a while till I move over to my own box.

I’ve testing an upload script, note the “images/” path.

[php]
copy($HTTP_POST_FILES[‘file’][‘tmp_name’],“images/”.$HTTP_POST_FILES[‘file’][‘name’]);
[/php]

it works but I want to use $_FILES. This one is a simple script and uses $HTTP_POST_FILES but integrating changes to my existing code is where i’m having problems.

Can you see anything in the code I posted a couple of posts ago that doesn’t look right?

Thanks again for your help, and patience :D