781
votes

This is a question you can read everywhere on the web with various answers:

$ext = end(explode('.', $filename));
$ext = substr(strrchr($filename, '.'), 1);
$ext = substr($filename, strrpos($filename, '.') + 1);
$ext = preg_replace('/^.*\.([^.]+)$/D', '$1', $filename);

$exts = split("[/\\.]", $filename);
$n    = count($exts)-1;
$ext  = $exts[$n];

etc.

However, there is always "the best way" and it should be on Stack Overflow.

29
One more way to get ext is strrchr($filename, '.');verybadbug
strrpos is the correct way (see my answer) but it needs an addition for the no-extension case.dkellner

29 Answers

1854
votes

People from other scripting languages always think theirs is better because they have a built-in function to do that and not PHP (I am looking at Pythonistas right now :-)).

In fact, it does exist, but few people know it. Meet pathinfo():

$ext = pathinfo($filename, PATHINFO_EXTENSION);

This is fast and built-in. pathinfo() can give you other information, such as canonical path, depending on the constant you pass to it.

Remember that if you want to be able to deal with non ASCII characters, you need to set the locale first. E.G:

setlocale(LC_ALL,'en_US.UTF-8');

Also, note this doesn't take into consideration the file content or mime-type, you only get the extension. But it's what you asked for.

Lastly, note that this works only for a file path, not a URL resources path, which is covered using PARSE_URL.

Enjoy

179
votes

pathinfo()

$path_info = pathinfo('/foo/bar/baz.bill');

echo $path_info['extension']; // "bill"
110
votes

Example URL: http://example.com/myfolder/sympony.mp3?a=1&b=2#XYZ

A) Don't use suggested unsafe PATHINFO:

pathinfo($url)['dirname']   🡺 'http://example.com/myfolder'
pathinfo($url)['basename']  🡺 'sympony.mp3?a=1&b=2#XYZ'         // <------- BAD !!
pathinfo($url)['extension'] 🡺 'mp3?a=1&b=2#XYZ'                 // <------- BAD !!
pathinfo($url)['filename']  🡺 'sympony'

B) Use PARSE_URL:

parse_url($url)['scheme']   🡺 'http'
parse_url($url)['host']     🡺 'example.com'
parse_url($url)['path']     🡺 '/myfolder/sympony.mp3'
parse_url($url)['query']    🡺 'aa=1&bb=2'
parse_url($url)['fragment'] 🡺 'XYZ'

BONUS: View all native PHP examples

64
votes

There is also SplFileInfo:

$file = new SplFileInfo($path);
$ext  = $file->getExtension();

Often you can write better code if you pass such an object around instead of a string. Your code is more speaking then. Since PHP 5.4 this is a one-liner:

$ext  = (new SplFileInfo($path))->getExtension();
23
votes

E-satis's response is the correct way to determine the file extension.

Alternatively, instead of relying on a files extension, you could use the fileinfo to determine the files MIME type.

Here's a simplified example of processing an image uploaded by a user:

// Code assumes necessary extensions are installed and a successful file upload has already occurred

// Create a FileInfo object
$finfo = new FileInfo(null, '/path/to/magic/file');

// Determine the MIME type of the uploaded file
switch ($finfo->file($_FILES['image']['tmp_name'], FILEINFO_MIME)) {        
    case 'image/jpg':
        $im = imagecreatefromjpeg($_FILES['image']['tmp_name']);
    break;

    case 'image/png':
        $im = imagecreatefrompng($_FILES['image']['tmp_name']);
    break;

    case 'image/gif':
        $im = imagecreatefromgif($_FILES['image']['tmp_name']);
    break;
}
20
votes

As long as it does not contain a path you can also use:

array_pop(explode('.', $fname))

Where $fname is a name of the file, for example: my_picture.jpg. And the outcome would be: jpg

20
votes

Do it faster!

In other words, please stop using pathinfo for this job. It's rather slow. Such low-level calls need to be very fast so I thought it was worth some research. I tried a few methods (with various string lengths, extension lengths, multiple runs each), here's some reasonable ones. I had to update the previous stats because php versions (and kernels and lots of other things) change, but on Linux servers, the takeaway is always the same.

/*   387 ns */ function method1($s) {return preg_replace("/.*\./","",$s);} // edge case problem
/*   769 ns */ function method2($s) {preg_match("/\.([^\.]+)$/",$s,$a);return $a[1];}
/*    67 ns */ function method3($s) {$n = strrpos($s,"."); if($n===false) return "";return substr($s,$n+1);}
/*   175 ns */ function method4($s) {$a = explode(".",$s);$n = count($a); if($n==1) return "";return $a[$n-1];}
/*   731 ns */ function method5($s) {return pathinfo($s, PATHINFO_EXTENSION);}
/*   732 ns */ function method6($s) {return (new SplFileInfo($s))->getExtension();}

Test string was "something.that.contains.dots.txt"; as you see, measurements were divided back to nanoseconds. SplFileInfo and pathinfo are great fellas, but for this kind of job it's simply not worth it to wake them up. For the same reason, explode() is cnosiderably faster than regex. Very simple tools almost always beat more sophisticated ones.

Side note: on Windows, results are totally different. I guess it's worth to run the numbers for your own case if you're using IIS.

Conclusion

This seems to be the Way of the Samurai:

function fileExtension($s) {
    $n = strrpos($s,".");
    return ($n===false) ? "" : substr($s,$n+1);
}

Some test cases

File name            fileExtension()
----------------------------------------
file                 ""
file.                ""
file.txt             "txt"
file.txt.bin         "bin"
file.txt.whatever    "whatever"
.htaccess            "htaccess"

(The last one is a bit special; it could be only an extension, or an empty extension with the pure name being ".htaccess", I'm not sure if there's a rule for that. So I guess you can go with both, as long as you know what you're doing.)

13
votes

1) If you are using (PHP 5 >= 5.3.6) you can use SplFileInfo::getExtension — Gets the file extension

Example code

<?php

$info = new SplFileInfo('test.png');
var_dump($info->getExtension());

$info = new SplFileInfo('test.tar.gz');
var_dump($info->getExtension());

?>

This will output

string(3) "png"
string(2) "gz"

2) Another way of getting the extension if you are using (PHP 4 >= 4.0.3, PHP 5) is pathinfo

Example code

<?php

$ext = pathinfo('test.png', PATHINFO_EXTENSION);
var_dump($ext);

$ext = pathinfo('test.tar.gz', PATHINFO_EXTENSION);
var_dump($ext);

?>

This will output

string(3) "png"
string(2) "gz"

// EDIT: removed a bracket

12
votes

Sometimes it's useful to not to use pathinfo($path, PATHINFO_EXTENSION). For example:

$path = '/path/to/file.tar.gz';

echo ltrim(strstr($path, '.'), '.'); // tar.gz
echo pathinfo($path, PATHINFO_EXTENSION); // gz

Also note that pathinfo fails to handle some non-ASCII characters (usually it just suppresses them from the output). In extensions that usually isn't a problem, but it doesn't hurt to be aware of that caveat.

9
votes

The simplest way to get file extension in PHP is to use PHP's built-in function pathinfo.

$file_ext = pathinfo('your_file_name_here', PATHINFO_EXTENSION);
echo ($file_ext); // The output should be the extension of the file e.g., png, gif, or html
9
votes

You can try also this (it works on PHP 5.* and 7):

$info = new SplFileInfo('test.zip');
echo $info->getExtension(); // ----- Output -----> zip

Tip: it returns an empty string if the file doesn't have an extension

8
votes

Sorry... "Short Question; But NOT Short Answer"

Example 1 for PATH

$path = "/home/ali/public_html/wp-content/themes/chicken/css/base.min.css";
$name = pathinfo($path, PATHINFO_FILENAME);
$ext  = pathinfo($path, PATHINFO_EXTENSION);
printf('<hr> Name: %s <br> Extension: %s', $name, $ext);

Example 2 for URL

$url = "//www.example.com/dir/file.bak.php?Something+is+wrong=hello";
$url = parse_url($url);
$name = pathinfo($url['path'], PATHINFO_FILENAME);
$ext  = pathinfo($url['path'], PATHINFO_EXTENSION);
printf('<hr> Name: %s <br> Extension: %s', $name, $ext);

Output of example 1:

Name: base.min
Extension: css

Output of example 2:

Name: file.bak
Extension: php

References

  1. https://www.php.net/manual/en/function.pathinfo.php

  2. https://www.php.net/manual/en/function.realpath.php

  3. https://www.php.net/manual/en/function.parse-url.php

6
votes

Here is an example. Suppose $filename is "example.txt",

$ext = substr($filename, strrpos($filename, '.', -1), strlen($filename));

So $ext will be ".txt".

6
votes

pathinfo is an array. We can check directory name, file name, extension, etc.:

$path_parts = pathinfo('test.png');

echo $path_parts['extension'], "\n";
echo $path_parts['dirname'], "\n";
echo $path_parts['basename'], "\n";
echo $path_parts['filename'], "\n";
5
votes
substr($path, strrpos($path, '.') + 1);
5
votes

A quick fix would be something like this.

// Exploding the file based on the . operator
$file_ext = explode('.', $filename);

// Count taken (if more than one . exist; files like abc.fff.2013.pdf
$file_ext_count = count($file_ext);

// Minus 1 to make the offset correct
$cnt = $file_ext_count - 1;

// The variable will have a value pdf as per the sample file name mentioned above.
$file_extension = $file_ext[$cnt];
4
votes

You can try also this:

 pathinfo(basename($_FILES["fileToUpload"]["name"]), PATHINFO_EXTENSION)
3
votes

I found that the pathinfo() and SplFileInfo solutions works well for standard files on the local file system, but you can run into difficulties if you're working with remote files as URLs for valid images may have a # (fragment identifiers) and/or ? (query parameters) at the end of the URL, which both those solutions will (incorrect) treat as part of the file extension.

I found this was a reliable way to use pathinfo() on a URL after first parsing it to strip out the unnecessary clutter after the file extension:

$url_components = parse_url($url); // First parse the URL
$url_path = $url_components['path']; // Then get the path component
$ext = pathinfo($url_path, PATHINFO_EXTENSION); // Then use pathinfo()
3
votes

Use substr($path, strrpos($path,'.')+1);. It is the fastest method of all compares.

@Kurt Zhong already answered.

Let's check the comparative result here: https://eval.in/661574

3
votes
ltrim(strstr($file_url, '.'), '.')

this is the best way if you have filenames like name.name.name.ext (ugly, but it sometimes happens

2
votes

This will work

$ext = pathinfo($filename, PATHINFO_EXTENSION);
2
votes

You can get all file extensions in a particular folder and do operations with a specific file extension:

<?php
    $files = glob("abc/*.*"); // abc is the folder all files inside folder
    //print_r($files);
    //echo count($files);
    for($i=0; $i<count($files); $i++):
         $extension = pathinfo($files[$i], PATHINFO_EXTENSION);
         $ext[] = $extension;
         // Do operation for particular extension type
         if($extension=='html'){
             // Do operation
         }
    endfor;
    print_r($ext);
?>
2
votes

$ext = preg_replace('/^.*\.([^.]+)$/D', '$1', $fileName);

preg_replace approach we using regular expression search and replace. In preg_replace function first parameter is pattern to the search, second parameter $1 is a reference to whatever is matched by the first (.*) and third parameter is file name.

Another way, we can also use strrpos to find the position of the last occurrence of a ‘.’ in a file name and increment that position by 1 so that it will explode string from (.)

$ext = substr($fileName, strrpos($fileName, '.') + 1);

2
votes

IMO, this is the best way if you have filenames like name.name.name.ext (ugly, but it sometimes happens):

$ext     = explode('.', $filename); // Explode the string
$my_ext  = end($ext); // Get the last entry of the array

echo $my_ext;
1
votes

If you are looking for speed (such as in a router), you probably don't want to tokenize everything. Many other answers will fail with /root/my.folder/my.css

ltrim(strrchr($PATH, '.'),'.');
1
votes

Although the "best way" is debatable, I believe this is the best way for a few reasons:

function getExt($path)
{
    $basename = basename($path);
    return substr($basename, strlen(explode('.', $basename)[0]) + 1);
}
  1. It works with multiple parts to an extension, eg tar.gz
  2. Short and efficient code
  3. It works with both a filename and a complete path
0
votes

Actually, I was looking for that.

<?php

$url = 'http://example.com/myfolder/sympony.mp3?a=1&b=2#XYZ';
$tmp = @parse_url($url)['path'];
$ext = pathinfo($tmp, PATHINFO_EXTENSION);

var_dump($ext);
0
votes

I tried one simple solution it might help to someone else to get just filename from the URL which having get parameters

<?php

$path = "URL will be here";
echo basename(parse_url($path)['path']);

?>

Thanks

-1
votes

Use

str_replace('.', '', strrchr($file_name, '.'))

for a quick extension retrieval (if you know for sure your file name has one).