如何在PHP中获取文件扩展名:从新手到行家(2025版)
\n\n你有没有想过,一个PHP开发人员每天要提取多少次文件扩展名?几十次,甚至上百次。上传头像、处理文档、验证图片——到处都需要搞清楚来的是个什么玩意儿:.jpg、.pdf,还是狡猾的.php.jpg。
"如何在PHP中获取文件扩展名?" 这个问题是Stack Overflow上最热门的问题之一。这也不奇怪。看起来难道不是再简单不过了吗?但魔鬼,一如既往,藏在细节里。到2025年,我们不仅拥有久经考验的pathinfo()和explode(),还有PHP 8.4提供的新功能,能让代码更简洁、更安全。
让我们来剖析5种可行的方法,它们的优缺点,以及各自适用的场景。开始吧!
\n\n1. 经典方法:pathinfo() —— 万法之王
\n\n最流行且最正确的方法是pathinfo()函数。它早在PHP 4时代就已出现,至今仍然适用。为什么?因为它很智能:它能处理系统路径分隔符,能处理URL,并且不会因为文件名中的点号而出错。
<?php\n$file = 'document.report.pdf';\n$extension = pathinfo($file, PATHINFO_EXTENSION);\n// 结果: 'pdf'\n?>\n\n但有一个细微之处。如果文件没有扩展名,pathinfo()会返回一个空字符串。不是null,也不是false——而恰恰是一个空字符串。这对于严格检查来说很重要。
<?php\n$file = 'README';\n$ext = pathinfo($file, PATHINFO_EXTENSION);\nvar_dump($ext); // string(0) ""\n?>\n\n何时使用:任何时候你需要快速可靠地获取扩展名。这是行业标准。
\n\n2. 老派方法:explode() 和 strrpos()
\n\n一些老派开发者更喜欢手动解析字符串。思路很简单:找到最后一个点号,然后取它之后的所有内容。
\n\n<?php\n$file = 'image.jpg';\n$parts = explode('.', $file);\n$extension = end($parts);\n// 结果: 'jpg'\n?>\n\n看起来能行。但有一个问题:explode()会创建一个数组,而end()会移动内部数组指针。虽然不是关键问题,但不够优雅。
一个性能更优的选择是 strrpos() + substr():
<?php\n$file = 'archive.tar.gz';\n$pos = strrpos($file, '.');\n$extension = $pos !== false ? substr($file, $pos + 1) : '';\n// 结果: 'gz'\n?>\n\n注意:strrpos()查找的是点号的最后一次出现。这是正确的——我们想要的是gz,而不是tar.gz。
何时使用:当pathinfo()不可用(特殊情况)时,或者你需要对逻辑有更多控制时。
3. 2025年的新方法:str_contains() 和 str_starts_with()
\n\nPHP 8.0引入了str_contains()和str_starts_with(),而PHP 8.4改进了多字节字符串处理。这开启了一些新的优雅方法。
<?php\n$file = 'photo.2025.jpg';\n\nif (str_contains($file, '.')) {\n $extension = substr($file, strrpos($file, '.') + 1);\n} else {\n $extension = '';\n}\n// 结果: 'jpg'\n?>\n\n优雅吗?不太算。但如果你需要检查一个文件是否为图片,str_ends_with()会是你的好帮手:
<?php\n$file = 'avatar.png';\n$isImage = str_ends_with($file, '.png') || str_ends_with($file, '.jpg');\n// true\n?>\n\n何时使用:用于快速检查特定扩展名,而无需提取整个扩展名。
\n\n4. 正则表达式:当你需要一步到位时
\n\n有时一个扩展名不够用。例如,你需要检查文件是否为安全图片,同时还要提取不带扩展名的文件名。这就是