Jump to content

Archived

This topic is now archived and is closed to further replies.

jo.nova

Extract file extension from an uploaded file

Recommended Posts

I'm trying to isolate the file extension of  uploaded files so that I can check them for validity.  For example, say I want to only accept ".zip" files:

Let's say the value of $_FILES['somefile']['name'] is "afile.zip"; I want to put just the extension in a variable and check it against a predefined set of strings.  I can setup the string filtering, but I don't know how to tell PHP to look at just the last three characters in a file name.

Any help?

Share this post


Link to post
Share on other sites
Use the function pathinfo()  http://www.php.net/manual/en/function.pathinfo.php
[code]<?php
$pi = pathinfo($_FILES['somefile']['name']);
echo '<pre>' . print_r($pi,true) . '</pre>';
?>[/code]

Ken

Share this post


Link to post
Share on other sites
another easy way of doing this is to use strrchr:

[code]<?php
$filename = 'something.zip';
$extension = strrchr($filename, '.');
?>[/code]

would yield '.zip' in $extension.  use substr() if you want to remove the period as well.

Share this post


Link to post
Share on other sites
That solution will only work for files with exactly one dot in them. It would break on files named, for example, something.ver.1.2.3.zip

Ken

Share this post


Link to post
Share on other sites
$allowed = array('image/gif', 'image/jpeg', 'image/png');
if (in_array($_FILES['upload']['type'], $allowed) {
  // Continue to process
}
else {
  // Tell them its bad
}

And replace ['upload'] with whatever the name of the input you use is.

Share this post


Link to post
Share on other sites
nay ken, strrchr() takes the LAST instance of the needle in the haystack, and returns it from there.  that's what's so handy about the function for this purpose.  you may be thinking of strchr().

Share this post


Link to post
Share on other sites
no need to apologize, the lovely PHP function-namers hardly made it obvious that strrchr is different from strchr.  but that's a beef for another day.

Share this post


Link to post
Share on other sites
WOW! Thanks, guys.  I go to lunch, and return to find an entire disseratation on my topic.  Much appreciated!  I'm lovin' PHP; way better than my boring-ass C++ class. Thanks!

Now, here's the next part I just realized:

How do I make the match case insenstive?  (Just in case someone happens to have their file extension in caps)

Share this post


Link to post
Share on other sites
[quote author=jo.nova link=topic=100459.msg396480#msg396480 date=1152808755]
I'm trying to isolate the file extension of  uploaded files so that I can check them for validity.  For example, say I want to only accept ".zip" files:

Let's say the value of $_FILES['somefile']['name'] is "afile.zip"; I want to put just the extension in a variable and check it against a predefined set of strings.  I can setup the string filtering, but I don't know how to tell PHP to look at just the last three characters in a file name.

Any help?
[/quote]

the thing is, an extension can be more than 3 characters so you wouldn't be doing a thorough job if you looked at the last 3 characters.
also, a file can be a text file and have a ".zip" extension or it could be a malicious exe and have a ".jpg" extension.
and if you plan to upload files such as tar.gz or tar.bz, etc (files with more than one extension - in this example, the file is an archived and compressed file), you would have to have some sort of work around to detect such extensions.


there are two options:
1. maintain an array of files with more than one extension that you permit. and first check if the last two blocks of characters (by a period) are in the array (using in_array()) that you maintain. if not, take the block of characters after the last period and check against that. i used to use this:
[code=php:0]
echo end(explode('.', $fileName));
[/code]
but i think akitchin's strrchr() is faster than an explode.

2. match the value of $_FILES['upload']['type'] or mime_content_type() against an array of allowed MIME's and allow or disallow accordingly.



you might find this useful: [url=http://www.ace.net.nz/tech/TechFileFormat.html]Almost Every file format in the world![/url]
or you could refer to /etc/mime.types if you're on a linux machine.

Share this post


Link to post
Share on other sites
So would this work?:

[code=php:0]//put filename in a variable before checking file extension
$filetypecheck = ($_FILES['FileName']['name']);

//put file's extension in a variable
$extension = strrchr($filetypecheck, '.');

// check to see if a file was entered and if that file is a valid type
if ((!$_FILES['FileName']['name']) || ($extension !== "zip" || "sit" || "jpg" || "pdf" || "tif" || "gif" || "eps" || "psd"))

// if not, add that error to our array
$errors[] = '- Your file to be printed (in one of the acceptable formats)';[/code]


Or does it have to be like this?:

[code=php:0]//put filename in a variable before checking file extension
$filetypecheck = ($_FILES['FileName']['name']);

//put file's extension in a variable
$extension = strrchr($filetypecheck, '.');

// check to see if a file was entered and if that file is a valid type
if ((!$_FILES['FileName']['name']) || ($extension !== "zip") || ($extension !== "sit") || ($extension !== "jpg") || ($extension !== "pdf") || ($extension !== "tif") || ($extension !== "gif") || ($extension !== "eps") || ($extension !== "psd"))

// if not, add that error to our array
$errors[] = '- Your file to be printed (in one of the acceptable formats)';[/code]


I'm new, so bear with me!

Share this post


Link to post
Share on other sites
it would be the latter format for the if() statement (ie. one condition for every possible extension), but three things:

1.  i would suggest simply putting all of your allowed extensions into an array and checking if the extension is in that array or not using in_array() (check the manual on the syntax).
2.  your logic is flawed.  it will check if the filename isn't set OR the extension isn't zip OR the extension isn't sit, etc.  it can't be both sit and zip at the same time, so it will always fail.  you'll need to change the extension checks to && (and operator).  using an array greatly simplifies this statement.
3.  strrchr() returns the '.' in the extension as well.  either change your allowed extensions to include the period or use substr() to remove the period in the file's extension (see manual for syntax).

Share this post


Link to post
Share on other sites
Gotcha.  Yeah, you're right about the logic; I just uploaded it and got erros no matter what the file type is.  Thanks for the advice!

Share this post


Link to post
Share on other sites
:Edit: akitchin has replied by the time i modified the code and posted it...but i'll post it anyway :)


first you would have to tell me if you intend to upload files that can have two valid extensions like tar.gz, etc.

if not, you would modify your code to this:

[code=php:0]
//put filename in a variable before checking file extension
$filetypecheck = trim($_FILES['FileName']['name']);

//put file's extension in a variable
$extension = strrchr($filetypecheck, '.');


$validTypes = array('.zip', '.sit', '.jpg', '.pdf', '.tif', '.gif', '.epf', '.psd');



// check to see if a file was entered and if that file is a valid type
if(!empty($filetypecheck) && in_array($extension, $validTypes))
{
echo 'valid upload format';
}
else
{
echo 'invalid upload format';
}
[/code]



there's a bunch of other things you should look into if you want to strictly allow only files of a certain type but it seems like you're not very particular about that so this should work ok as far as i know.

hope that helped :)

Share this post


Link to post
Share on other sites
akitchin, thanks everything you said worked out great!

Koobi, thanks man, got it working in the meantime.  Here's how I implemented it:

[code=php:0]
//put filename in a variable before checking file extension
$filetypecheck = ($_FILES['FileName']['name']);
//put file's extension in a variable
$extension = strrchr($filetypecheck, '.');

//make an array of allowed extensions
$allowext = array(".zip",".sit",".tif",".jpg",".pdf",".eps",".gif",".psd");

// check to see if a file was entered and if that file is a valid type
if ((!$_FILES['FileName']['name']) || (!in_array($extension, $allowext)))
// if not, add that error to our array
$errors[] = '- Your file to be printed (in one of the acceptable formats)';
[/code]


We're a printshop, so we're probably not gonna get anything like .gz files from customers since almost the entire industry is using Macs.

Thanks guys!  I hope to get as proficient at this so that I can help others someday as well!

Share this post


Link to post
Share on other sites

×

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.