- image/png
If you only want to allow images there is a very simple way that it can be done using the mime_content_type() function, which determines the type from the file its self rather than relying on the information sent from the browser.
Here is an example of the functions usage
- echo mime_content_type('image.png');
all image mime types will start with image/
so for image validation all that needs to be done is.
- <?php
- $type = mime_content_type($_FILES['name']['tmp_name']);
- $type = explode('/', $type);
- if (strtolower($type[0]) === 'image'){
- // its an image.
- }else{
- // its not an image.
- }
- ?>
Additional to this it is advisable to check the extension of the file, which can be obtained using the following method
- $ext = strtolower(end(explode('.', $_FILES['name']['name'])));
again the strtolower is just to make sure that if the file has a uppercase extension and is valid, it will still pass.
Then we need a list of allowed extensions to compare with.
- $allowed = array('png', 'jpg', 'gif', 'jpeg', 'svg');
then we need to check the extension we got from the file name to make sure its in the list of allowed types, php has a function for this called in_array(). so putting it all together we have.
now we should really combine these two checks into one nice clean statement, so using the && opperator on the if statement we end up with...
- <?php
- $allowed = array('png', 'jpg', 'gif', 'jpeg', 'svg');
- $ext = strtolower(end(explode('.', $_FILES['name']['name'])));
- $type = mime_content_type($_FILES['name']['tmp_name']);
- $type = explode('/', $type);
- if (strtolower($type[0]) === 'image' && in_array($ext, $allowed) === true){
- // upload can continue.
- }else{
- // abort abort abort...
- }
- ?>
So now we are 100% sure we have a safe file ? no !!
There is no way to be completely sure its possible there is a way I don't know about to trick this, its possible there is a way nobody knows about yet.
so saving the file with its original name is not a good idea,because if someone does manage to upload a .php file and it is saved as a .png then there is no way that they will be able to get it to execute.
Happily the correct extension can easily be determined by looking at the mime type, so once we have decided that the image is safe to upload we need to work out what to call it and where to save it.
Lets start with a list of extensions that will go with each of the allowed mime types.
- <?php
- $extension['image/png'] = 'png';
- $extension['image/jpeg'] = 'jpg';
- $extension['image/gif'] = 'gif';
- $extension['image/svg+xml'] = 'svg';
- ?>
Now as we know the mime type of the file we can work out what its extension should be...
- $saveas = $extension[$type];
It is also best to generate a random name for the file (if possible for your system) this can be done is a number of ways, alex's random password tutorial is a good method (ill be using a one line method for the purpose of this tutorial, its up to you), however we also need to make sure that the file does not exist, before we decide on a name for it. This is done using a while loop...
First we need to decide on a name, then we need to generate a new random name while that name exists in the folder, hopefully this will become more clear with an example...
- $savepath = '/path/where/file/is/saved/'.$name.'.'.$saveas;
- <?php
- $extension['image/png'] = 'png';
- $extension['image/jpeg'] = 'jpg';
- $extension['image/gif'] = 'gif';
- $extension['image/svg+xml'] = 'svg';
- $saveas = $extension[$type];
- $name = md5(rand(0, 9999999));
- while (file_exists('/path/where/file/is/saved/'.$name.'.'.$saveas)){
- $name = md5(rand(0, 9999999));
- }
- $savepath = '/path/where/file/is/saved/'.$name.'.'.$saveas;
- move_uploaded_file($_FILES['name']['tmp_name'], $savepath);
- ?>
The final step is to decide what happens when the file is not valid (my advice is to tell the user nothing and just kill the script) and combine these two parts...
The final script looks like this...
- <?php
- $allowed = array('png', 'jpg', 'gif', 'jpeg', 'svg');
- $ext = strtolower(end(explode('.', $_FILES['name']['name'])));
- $type = mime_content_type($_FILES['name']['tmp_name']);
- $type = explode('/', $type);
- if (strtolower($type[0]) === 'image' && in_array($ext, $allowed) === true){
- $extension['image/png'] = 'png';
- $extension['image/jpeg'] = 'jpg';
- $extension['image/gif'] = 'gif';
- $extension['image/svg+xml'] = 'svg';
- $saveas = $extension[$type];
- $name = md5(rand(0, 9999999));
- while (file_exists('/path/where/file/is/saved/'.$name.'.'.$saveas)){
- $name = md5(rand(0, 9999999));
- }
- $savepath = '/path/where/file/is/saved/'.$name.'.'.$saveas;
- move_uploaded_file($_FILES['name']['tmp_name'], $savepath);
- }else{
- die();
- }
- ?>
