Page 1 of 2

File Uploads (extensions, renaming)

Posted: Mon Mar 14, 2005 6:17 pm
by furiousweebee
Hey,

I'm sure this is easy for many of you, but I'm only just starting out with using PHP so I'm not sure where to go from here. Anyway, my problems/tasks are as follows:

- I have a form which both adds information to MySQL, and uploads a file. The file uploading works, but the way I have it working, it gives all uploaded files a JPG extension. I'd like to retain the extension of the original file.

- The uploaded file uses a name taken from one of the other form fields. This is purely so that I can later display the appropriate image (on another page of my site). Instead, I'd like to be able to rename the file based on some abbreviations, and then a number which is today's date (eg my file might end up like this: "DJ-11.05.05" (being short for "Disc Jockey", uploaded on 11th May 2005).

I did hunt around these forums for existing code but couldn't find quite what I was looking for/wasn't sure exactly how to implement it.

Below is my code:

Code: Select all

<FORM ENCTYPE=&quote;multipart/form-data&quote; ACTION=&quote;<? $PHP_SELF ?>&quote; METHOD=&quote;POST&quote;>

<strong>Name:</strong><br>
<INPUT type=&quote;text&quote; name=&quote;name&quote; size=&quote;40&quote;><br><br>

<strong>Website:</strong><br>
http://<INPUT type=&quote;text&quote; name=&quote;website&quote; size=&quote;50&quote;><br><br>

<strong>Type:</strong><br>
<select name=&quote;type&quote;>
<option selected>Band</option>
<option>Label</option>
<option>Site</option>
</select><br><br>

<strong>Short Description:</strong><br>
<INPUT type=&quote;text&quote; name=&quote;description&quote; size=&quote;78&quote;><br><br>

<strong>Banner / Logo:</strong><br>
<INPUT type=&quote;file&quote; name=&quote;fnt&quote; size=&quote;78&quote;><br><br>
<input type=&quote;submit&quote; name=&quote;enter_data&quote; value=&quote;Submit&quote;></TD>
</form>

Code: Select all

<?

if ($_POST['enter_data']) {

if ($fnt != "") {
$name = stripslashes($name);
copy($_FILES['fnt']['tmp_name'], "../images/ads/$name.jpg");
$resource = mysql_query("INSERT into sponsors (name, website, description, type, pic) VALUES ('$name', '$website', '$description', '$type', 'Y')") or die(mysql_error()); }

else {
$resource = mysql_query("INSERT into sponsors (name, website, description, type) VALUES ('$name', '$website', '$description', '$type')") or die(mysql_error()); }

MYSQL_CLOSE();
echo"<META HTTP-EQUIV=refresh content=0;URL=index.php>";

}

?>

Posted: Mon Mar 14, 2005 6:50 pm
by Chris Corbyn
Don't use $name by the way for POST... it's bad practise. Always use $_POST['name'];

OK to the question(s). To avoid the .jpg extension remove the .jpg extensions from the last argument in copy().

Code: Select all

$name = $_POST['name']; //Always do it like this
copy($_FILES['fnt']['tmp_name'], "../images/ads/$name");
For the abbreviations... that'll be damn hard if you want it to recognise words and abbreviate based on them. But to trim the filename to a fixed length and append the date (and perhaps time to avoid duplicates :? ) would be easy.

Untested (may need some tweaking)...

Code: Select all

preg_match('/^(.+)\.?([^\.]+?)$/', $_POST['name'], $base_and_ext); //Get bits into array
$base = substr($base_and_ext[1], 0, 4); //Allows up to 4 Chars in filename
$ext = $base_and_ext[2]; //The extension
$date = date("d.m.y");
copy($_FILES['fnt']['tmp_name'], '../images/ads/'.$base.'_'.$date.'.'.$ext); //Copy the newly named file
If run on 13th March 2005 the above should turn Saturday.jpeg into Satu_13.03.05.jpeg ;-)

EDIT: Modified regexp for ^ and $ and corrected position of $ext in filename :oops:

Posted: Mon Mar 14, 2005 7:15 pm
by furiousweebee
Thanks, I gave that a shot and ended up with the code below. However, when using the name of "Test2" on my form, I ended up with the following filename (including extension): "14.03.05.2". Note that I changed it to 10 characters.

Code: Select all

if ($fnt != "") {
$name = stripslashes($_POST['name']);
preg_match('/^(.+)\.?([^\.]+?)$/', $_POST['name'], $base_and_ext); // Get bits into array
$base = substr($base_and_ext[1], 0, 10); // Allows up to 10 chars in filename
$ext = $base_and_ext[2]; // The extension
$date = date("d.m.y");
copy($_FILES['fnt']['tmp_name'], "../images/ads/$base_$date.$ext"); //Copy the newly named file

Posted: Tue Mar 15, 2005 2:18 am
by hongco
i would use strrchr() function to get the extension of the uploaded file
if you use something like this for file, says, mypic.jpg

Code: Select all

$ext = strrchr($HTTP_POST_FILES['fnt']['name'], ".");
echo $ext;  // result  .jpg  (with the dot in front)
It will always get the last dot (.). So if you have mypic.1.2.3.jpg...it still gives .jpg as the result

Posted: Tue Mar 15, 2005 2:43 am
by feyd
be aware that a file's extension does not necessarily determine what kind of file it actually is.

Posted: Tue Mar 15, 2005 2:46 am
by hongco
feyd wrote:be aware that a file's extension does not necessarily determine what kind of file it actually is.
yeah, i thought check file type would help, but somehow, if I change the extension from *.exe to *.jpg, the uploading script that i am working still consider the file as an image type. Am i doing something wrong or there is a way to determine file's true type?

Thanks!

Posted: Tue Mar 15, 2005 3:27 am
by feyd
because of the ease of forging a fake file, the only way to be sure is binary recognition, basically.. to analyze images of "normal" web use, getimagesize() can be used.

Posted: Tue Mar 15, 2005 3:53 am
by hongco
feyd wrote:because of the ease of forging a fake file, the only way to be sure is binary recognition, basically.. to analyze images of "normal" web use, getimagesize() can be used.
thank you feyd :)
This also gives me the idea how to determine mp3 file- the id3 tag. I will allow my website members upload their own singing with mp3 format.

Posted: Tue Mar 15, 2005 6:02 am
by hongco
just wanted to post this helpful link:

http://www.flash-db.com/remoting/?servi ... Multimedia

This class gives info on mp3 file.

I tested it, and it works great for my need

Posted: Tue Mar 15, 2005 7:58 am
by furiousweebee
So, back to my original topic hehe... I should end up with something like this?

Code: Select all

if ($fnt != "") {
$name = stripslashes($_POST['name']);
preg_match('/^(.+)\.?([^\.]+?)$/', $_POST['name'], $base_and_ext);
$base = substr($base_and_ext[1], 0, 10);
$ext = strrchr($HTTP_POST_FILES['fnt']['name'], ".");
$date = date("d.m.y");
copy($_FILES['fnt']['tmp_name'], "../images/ads/$base_$date.$ext");

Posted: Tue Mar 15, 2005 8:59 am
by Chris Corbyn
OK I tested my RegExp (preg_match() part) but it doesn't work as I'd hoped.

I'll try to re-write the regexp unless somebody does it before me.

The idea of just using strrchr() could be manipulated to do the same task too I guess but a pattern match would be nicer.

It just needs the preg_match() line tweaking and it'll work :-D

Posted: Tue Mar 15, 2005 4:44 pm
by furiousweebee
Sweet, that would be great if you could. The other thing I realised, is that I'm going to have to be able to recall this entire filename to later display it with the appropriate record. So instead of putting 'Y' into the 'pic' field in MySQL, I'm going to have to store the filename (or make another column for the name).

Posted: Fri Mar 18, 2005 4:48 am
by furiousweebee
I've been playing around with it, and I came up with the following code:

Code: Select all

$name = $_POST['name'];

if (isset($_POST['enter_data'])) {
	if (!empty($_FILES['fnt'])) {
		$name_short = stripslashes(substr($_POST['name'], 0, 5));
		$extension = strrchr($_FILES['fnt']['name'], ".");
		$filename = $name_short."_".date("d.m.y").$extension;
		move_uploaded_file($_FILES['fnt']['tmp_name'], "../images/ads/".$filename);
		$resource = mysql_query("INSERT into sponsors (name, website, description, type, pic) VALUES ('$name', '$website', '$description', '$type', '$filename')") or die(mysql_error()); }
	else {
		$resource = mysql_query("INSERT into sponsors (name, website, description, type, pic) VALUES ('$name', '$website', '$description', '$type', 'n')") or die(mysql_error()); }

MYSQL_CLOSE();
echo"<META HTTP-EQUIV=refresh content=0;URL=index.php>";
	}
Now, this is working perfectly EXCEPT, if there's no file uploaded, I want it to write 'n' into the "pic" field of the table. It's not doing that. It's putting the uploaded filename (without extension), and I can't seem to get around it. Any ideas?

Posted: Fri Mar 18, 2005 6:22 am
by n00b Saibot
Hint: check for $_FILES['fnt']['size'] being equal to 0. ;)

Posted: Fri Mar 18, 2005 8:05 am
by furiousweebee
So change:

Code: Select all

if (!empty($_FILES['fnt'])) {
To:

Code: Select all

if ($_FILES['fnt']['size'] !== '0') {
?

Or did you mean I should add it to the second part of my loop (after the "else")?