Check file extension in upload form in PHP [duplicate]
I check the file extension for upload or not uploaded. My example methods worked, but now I need to understand if my methods (using pathinfo
) is true. Is there another better and faster way?
$filename = $_FILES['video_file']['name'];
$ext = pathinfo($filename, PATHINFO_EXTENSION);
if ($ext !== 'gif' || $ext !== 'png' || $ext !== 'jpg') {
echo 'error';
}
Solution 1:
Using if( $ext !== 'gif'
) might not be efficient. What if you allow like 20 different extensions?
Try:
$allowed = array('gif', 'png', 'jpg');
$filename = $_FILES['video_file']['name'];
$ext = pathinfo($filename, PATHINFO_EXTENSION);
if (!in_array($ext, $allowed)) {
echo 'error';
}
Solution 2:
Checking the file extension is not considered best practice. The preferred method of accomplishing this task is by checking the files MIME type.
From PHP:
<?php
$finfo = finfo_open(FILEINFO_MIME_TYPE); // Return MIME type
foreach (glob("*") as $filename) {
echo finfo_file($finfo, $filename) . "\n";
}
finfo_close($finfo);
?>
The above example will output something similar to which you should be checking.
text/html
image/gif
application/vnd.ms-excel
Although MIME types can also be tricked (edit the first few bytes of a file and modify the magic numbers), it's harder than editing a filename. So you can never be 100% sure what that file type actually is, and care should be taken about handling files uploaded/emailed by your users.
Solution 3:
Personally,I prefer to use preg_match() function:
if(preg_match("/\.(gif|png|jpg)$/", $filename))
or in_array()
$exts = array('gif', 'png', 'jpg');
if(in_array(end(explode('.', $filename)), $exts)
With in_array()
can be useful if you have a lot of extensions to validate and perfomance question.
Another way to validade file images: you can use @imagecreatefrom*()
, if the function fails, this mean the image is not valid.
For example:
function testimage($path)
{
if(!preg_match("/\.(png|jpg|gif)$/",$path,$ext)) return 0;
$ret = null;
switch($ext)
{
case 'png': $ret = @imagecreatefrompng($path); break;
case 'jpeg': $ret = @imagecreatefromjpeg($path); break;
// ...
default: $ret = 0;
}
return $ret;
}
then:
$valid = testimage('foo.png');
Assuming that foo.png
is a PHP-script file with .png
extension, the above function fails. It can avoid attacks like shell update and LFI.