Over time, I’ve seen a wide range of scripts which for one reason or another have had the need to grab the extension from a file name or path (E.g. “gif” from “mypic.gif”). Oftentimes the solution tends to fall back on what the task appears to need: string manipulation. Though, as you’ll see, this may not be the best approach to take.
To make things a little clearer for people who can visualise code more easily than paragraphs of text, here are a few examples of what I’ve seen used in the past. The samples are mostly compacted onto a single line but if you’re not comfortable with multiple things happening in one line, feel free to expand them into multiple steps. In all cases, $ext ends up being “gif” .
$filename = 'mypic.gif'; // 1. The "explode/end" approach $ext = end(explode('.', $filename)); // 2. The "strrchr" approach $ext = substr(strrchr($filename, '.'), 1); // 3. The "strrpos" approach $ext = substr($filename, strrpos($filename, '.') + 1); // 4. The "preg_replace" approach $ext = preg_replace('/^.*\.([^.]+)$/D', '$1', $filename); // 5. The "never use this" approach // From: http://php.about.com/od/finishedphp1/qt/file_ext_PHP.htm $exts = split("[/\\.]", $filename); $n = count($exts)-1; $ext = $exts[$n];
Forgetting approach number 5 (the “never use this” approach!), they seem fairly reasonable ways of parsing the $filename string and grabbing the extension. So much so that those approaches can be found dotted around the interweb when people ask the question “How to get the file extension in PHP?”
Speed, baby, speed!
Because these are commonly used snippets of code, I decided to pitch them against each other and find out which was the most efficient–by that I simply mean the fastest processing–method just to satisfy my curiosity. The exact details of how they were tested I don’t plan to go into in this post, but here is what I found. On order of fastest to slowest were:
- strrchr
- closely followed by strrpos
- then preg_replace
- with explode/end coming in almost twice as slow as the str* methods
Great, so the idea is to use the $ext = substr(strrchr($filename, '.'), 1); approach from now on? Hold on there sonny boy, not so fast! There is another contender which has not been considered yet (though some of you would have been screaming his name from the start). Time to introduce the pathinfo function.
“Hello”, says pathinfo.
Pathinfo does a number of things, depending on what we ask of it, but put simply it returns (path) information about a filepath. Full details can be found on the handy dandy pathinfo page in the PHP manual. Explore the PHP manual page when you get time, but for the purpose of this blog post I’ll hone in to one specific use of the function: getting the file extension. In order to do that, we simply call the function passing along the full filename and a ‘flag’ (a constant which dictates the behaviour of the function) asking for the extension only.
$filename = 'mypic.gif'; $ext = pathinfo($filename, PATHINFO_EXTENSION);
That’s all there is to it! In my opinion, this approach ‘reads’ much more easily than the mess of nested function calls and playing around with string positions, regular expressions, etc.. It is concise and to the point: call pathinfo and only give me back the extension. Simple.
Now for the icing on the cake. When pitched against the other methods detailed above, this call to pathinfo beats all of the others into submission. At least in my testing, it is the fastest method of all (though in random hiccups strrchr does win in around 1% of tests) being on average 1/10th faster than even the strrchr approach.
Summary, or “the bit lazy people should read”
So, to cut a long blog post short, the method that I’ll be using to grab the file extension is simply:
$filename = 'mypic.gif'; $ext = pathinfo($filename, PATHINFO_EXTENSION);
What do you currently use? Have you had any problems using pathinfo, any particular quirks or annoyances?
27 Comments on PHP Get File Extension.
I used the explode() method which was really clean to me. explode() never annoyed me but it was a bit longer since you need to work on the array to print out the extension. (without die, I suppose).
pathinfo() is really easy as compared to all the other contenders but proper profiling still needs to be done to find the fastest contender in terms of speed. I don’t really care about those 0.00001ms of speed but some do..
I know that someone are very, very interested in scraping away those thousands of milliseconds from their scripts — to a degree it also interests me in a “hmm, lets see what we can do” way rather than a necessity for each and every line of code I ever create.
Personally, I think that
pathinfo(..., PATHINFO_EXTENSION)is by far the easiest code snippet to read and understand quickly what is going on, compared to the other alternatives posted here.Hey. Just dropping a note of appreciation. Nice when someone publishes something that is simple and direct as to the best practice, given the myriad of options available to you in PHP.
Thanks!
If you are making a file upload script, it is crucial that you use the pathinfo method to finding the true file extension. Because it is possible to fake out php by just renaming the file’s extension. Then when you upload it, if you use explode / strchr method, it will give you the wrong extension.
I’m not sure how providing a file extension which does not match the file content will “fake out” PHP but I do know that whichever of the methods listed above is used, they each produce the same result. If explode / strchr methods give the “wrong” extension, so will pathinfo.
Oh sorry, I was thinking of something else: http://www.jellyandcustard.com/2006/01/19/php-mime-types-and-fileinfo/
But that’s only really important for file uploads, and I guess you were mainly talking about files that were already on the server. Myyy badd.
if you can live with the dot:
strrchr($name,’.')
will return “.php”
That’s about ~2x faster than pathinfo()
Thank you.
Nice and direct.
Beautifully explained. Thanks!
This is a great post, with useful, practical information. Hat’s off to you, sir.
what about
$filename = ‘my.pic.gif’;
Robin,
pathinfo('my.pic.gif', PATHINFO_EXTENSION)would returngifas expected.Thanks for this
There are so many functions in PHP, and I have now discovered a new one
And what about this:
$fileinfo = “file.tar.gz”;
Would it return the proper tar.gz or just the gz?
Any way to easy do this or do we have to use the explode and check for every filetype? :/
Cheers,
Thanks for the comment Josso. In that case gz would be returned as the file extension (which is fine if you see it as a gzipped tar file, and not a “tar gzip” file). It would be easy enough to look for the
tarif you needed to for whatever reason.Josso:
A file named file.tar.gz is a gzip file, so ‘gz’ is the proper extension. If you gunzip it, you are left with a tarball with a ‘tar’ extension. This is all by design. An alternate extension for a gzipped tarball is .tgz, however it’s more technically valid to have .tar.gz. It does matter when you run into an instance where you want to gunzip without extracting the tarball.
Ummm, NO! Do NOT use explode, strchr, substr etc. to parse filenames like this. You will end up with bugs and potential security problems. Why? Well, think about all the different permutations of filenames that can cause problems. This is especially true of user-input strings (like for file uploads, etc.). Use the pathinfo() function.
Please update your article to reflect this so the monkeys of the world will stop using strchr in their code to parse paths. Thanks.
Would the monkey please take care to actually read the article in its entirety? The advice in the article is indeed to use the pathinfo function and there’s even a “bit lazy people should read” which summarises the post in under 30 words, but thanks for your concern.
Thank you.
Nice and direct.
Great article specifically for the speed testing of the different options listed. Came in handy for a directory listing script I’m working on. Thanks!
[...] get file extension comparison [...]
i think that the explode method is not a reliable one.B’coz try uploading a file named filename.gif.php, the explode method will return the extension as .gif and it ignores the .php part. its a potentional security flow as any one can uplaod the php file and execute it.
So i would recommend using the pathinfo function.
Absolutely, that’s the entire point of this article. Thanks for commenting.
Great accurate article. Thanks for condensing the functions into one lines as well, I always try to make my code as concise as possible. Thanks.
Thanks Eric. I too like concise code so long as it’s concise and readable; if the code is just mushed together and obfuscated for the sake of keeping it small, then that’s no so cool.
thank you very much
helpful and direct..
keep it up!