Как мне получить расширение файла в PHP?


723

Этот вопрос вы можете прочитать везде в Интернете с различными ответами:

$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];

и т.п.

Тем не менее, всегда есть «лучший способ», и он должен быть в переполнении стека.


15
Источник вопроса и ответа: cowburn.info/2008/01/13/get-file-extension-comparison
— salathe

5
Еще один способ получить strrchr($filename, '.');
— добро

Ответы:


1776

Люди из других языков сценариев всегда думают, что их лучше, потому что у них есть встроенная функция, а не PHP (я сейчас смотрю на Pythonistas :-)).

На самом деле, оно существует, но мало кто это знает. Знакомьтесь pathinfo():

$ext = pathinfo($filename, PATHINFO_EXTENSION);

Это быстро и встроенно. pathinfo()может дать вам другую информацию, такую ​​как канонический путь, в зависимости от константы, которую вы передаете ей.

Помните, что если вы хотите иметь возможность работать с не ASCII-символами, вам нужно сначала установить локаль. НАПРИМЕР:

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

Также обратите внимание, что это не учитывает содержимое файла или mime-тип, вы получаете только расширение. Но это то, что вы просили.

Наконец, обратите внимание, что это работает только для пути к файлу, а не для пути к ресурсам URL, который покрывается с помощью PARSE_URL.

наслаждаться


62
Я хотел бы проголосовать за это дважды. Я не могу сказать вам, сколько кода я смог заменить, используя pathinfo
— Марк

8
Я тоже. Вот почему я положил это здесь!
— е-сат

7
Как знать, оказывается, есть лучший способ.
— Бен

19
@khizaransari Вы должны искать другого хостинг-провайдера, тот, который вы получили, глуп. На самом деле, я имею в виду это. Нет никаких причин отключать эту функцию. Скажи им это. В качестве обходного пути: function get_ext($fname){ return substr($fname, strrpos($fname, ".") + 1); }убедитесь, что файл имеет расширение, однако он может делать что угодно, когда вы передаете путь в качестве аргумента!
— Люк

12
мое представление о PHP по сравнению с python полностью изменилось, теперь, когда я знаю об этой функции: O
— Томмазо Барбугли

166

pathinfo()

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

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

14
Начиная с PHP 5.5 ->echo pathinfo('/foo/bar/baz.bill')['extension'];
— Salman A

1
Это даже работает на этом уровне (Twitter json): $ ext = pathinfo ($ result-> extended_entities-> media [0] -> video_info-> варианты [1] -> URL, PATHINFO_EXTENSION);
— KJS

101

Пример URL: http://example.com/myfolder/sympony.mp3?a=1&b=2#XYZ

А) Не используйте предложенные небезопасные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'

Б) Используйте 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'

БОНУС: Просмотреть все нативные примеры PHP


3
Этот ответ охватывает все, например. файл как с foo_folder/foo-file.jpg?1345838509треском провалится с просто pathinfo, спасибо

1
Не совсем по теме, но это точно решило мою проблему!
— Хауи

7
Не забывайте ничего! parse_urlдля URL и pathinfoдля пути к файлу.
— Наби КАЗ

1
Что вы имеете в виду "забыть путь информации"? Вы используете это в решении!
— Осень Леонард

1
@AutumnLeonard Нет, он просто показал различия между pathinfo и parse_url.

59

Также есть SplFileInfo:

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

Часто вы можете написать лучший код, если передаете такой объект вместо строки. Ваш код более понятен. Начиная с PHP 5.4 это однострочный текст:

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

Фантастика, все объекты спущены :)
— Кристофер Чейз

2
Обратите внимание, что ->getExtension()доступно в SplFileInfo начиная с PHP 5.3.6.
— Матиас

1
@matthias: имейте в виду, что SPL можно отключить в версиях PHP, предшествующих версии PHP 5.3.0. Если вы все еще не используете PHP 5.3, но 5.2 или ниже, этот ответ, скорее всего, не подходит для стабильного кода. В противном случае вы можете стабилизировать свой код, требуя конкретной версии PHP, и в противном случае выручите.
— Хакре

@hakre Хотя вы правы, говоря, что «его можно отключить в версиях, предшествующих 5.3.0», расширение SPL тем не менее компилируется по умолчанию в PHP 5.0.0. Так что этот комментарий действительно имеет смысл для людей, которые вынуждены использовать PHP 5.2 или ниже и не хотят уходить в отставку, используя определенные классы SPL.
— Маттиас

да, просто мертвая версия пух :)
— хакре

23

Ответ E-удовлетворительного является правильным способом определения расширения файла.

В качестве альтернативы, вместо того, чтобы полагаться на расширение файлов, вы можете использовать fileinfo для определения типа файлов MIME.

Вот упрощенный пример обработки изображения, загруженного пользователем:

// 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;
}

1
Это единственный правильный ответ. Я не понимаю, почему люди проголосовали за других. Да, этот подход требует больше усилий от разработчика, но он повышает производительность (хотя и мало, но это так). Пожалуйста, обратитесь это .
— Бхавик Шах

2
@Bhavik: В некоторых случаях нам может понадобиться только расширение файла, они о проверке MIME-типа. Но фактический вопрос касается расширения файла, а не типа файла. Так что это НЕ лучший ответ на этот вопрос. (пока ответ)
— Саси Варна Кумар

этот переключатель требует дополнительных скобок
— rsb2097

16

Пока он не содержит путь, вы также можете использовать:

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

Где $fnameэто имя файла, например: my_picture.jpg. И результат будет:jpg


@ Почему у этого есть 3 отрицательных голоса? это дает правильный результат. Пожалуйста, объясните
— railsbox

Это не так, просто это не лучший способ сделать это. Проголосовал за немного баланса.

Это лучший способ, когда вам нужно реальное расширение и имя файла может содержать несколько символов. Например, загруженные пользователем фотографии в моем случае.
— Раули Раджанде

2
Это не удастся, если имя файла не имеет расширения. Попробуйте передать «myfile», и он вернет «myfile». Правильное возвращаемое значение - пустая строка как расширение в этом случае использования.
— Пмонт

Это неправильно в том, что array_pop () выдаст уведомление, потому что в качестве параметра он принимает указатель.
— Юрсикс

12

1) Если вы используете (PHP 5> = 5.3.6), вы можете использовать SplFileInfo :: getExtension - Получает расширение файла.

Пример кода

<?php

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

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

?>

Это будет выводить

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

2) Другой способ получить расширение, если вы используете (PHP 4> = 4.0.3, PHP 5) - это pathinfo

Пример кода

<?php

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

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

?>

Это будет выводить

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

// РЕДАКТИРОВАТЬ: убрал скобку


12

Иногда полезно не использовать pathinfo($path, PATHINFO_EXTENSION). Например:

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

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

Также обратите внимание, что pathinfoне удается обработать некоторые не-ASCII символы (обычно это просто подавляет их из вывода). В расширениях это, как правило, не проблема, но не больно осознавать это предостережение.


6
@ e-sat: Согласно Википедии, они являются двумя расширениями: UNIX-подобные файловые системы используют другую модель без разделенных метаданных расширения. Точечный символ - это просто еще один символ в главном имени файла, и имена файлов могут иметь несколько расширений, обычно представляющих вложенные преобразования, такие как files.tar.gz .
— Аликс Аксель

1
А если у нас есть точка в названии продукта? Пример:test.19-02-2014.jpeg
— Марио Радоманана

Это не удастся, так как /root/my.folder/my.css ltrim(strrchr($PATH, '.'),'.')работает как pathinfo, но без токенизации всего.
— Рэй Фосс

8

Самый простой способ получить расширение файла в PHP - использовать встроенную в PHP функцию 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

8

Вы также можете попробовать это (это работает на PHP 5. * и 7):

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

Совет: он возвращает пустую строку, если файл не имеет расширения


7

Извините ... "Короткий вопрос; но НЕ короткий ответ"

Пример 1 для 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);

Пример 2 для 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);

Вывод примера 1:

Name: base.min
Extension: css

Вывод примера 2:

Name: file.bak
Extension: php

Ссылки

  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

Быстрое исправление будет что-то вроде этого.

// 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];

Почему бы просто не использовать встроенную функцию php для целей php.net/manual/en/function.pathinfo.php вместо длинного кода
— Шахбаз

1
Помимо точки зрения Шахбаза, вы также можете сделать $file_ext = end(explode('.', $filename));все, что в этом ответе, в одной строке вместо четырех.
— tvanc

@ Амелия Что если у тебя есть .tar.gz. Это не будет работать, поэтому, если вам нужно получить полное расширение, используйте его, например, ltrim(strstr($filename, '.'), '.');чтобы получить полное расширение вместо неправильно gz.
— Марин Саговац

6

Вот пример. Предположим, что $ filename это "example.txt",

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

Так что $ ext будет ".txt".


6

pathinfo - это массив. Мы можем проверить имя каталога, имя файла, расширение и т.д .:

$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
substr($path, strrpos($path, '.') + 1);

1
Это не удастся с /root/my.folder/my.css
— Рэй Фосс

1
Это должно работать правильно: substr ($ path, strrpos ($ path, '.') + 1); Примечание: этот метод быстрее, чем любые другие решения выше. Попробуйте бенчмарк, используя наш собственный скрипт.
— Аббас


4
ltrim(strstr($file_url, '.'), '.')

это лучший способ, если у вас есть имена файлов, такие как name.name.name.ext (некрасиво, но иногда бывает



3

Я обнаружил , что pathinfo()и SplFileInfoрешение хорошо подходит для стандартных файлов в локальной файловой системе, но вы можете столкнуться с трудностями , если вы работаете с удаленными файлами , поскольку URL - адрес для действительных изображений могут иметь #(идентификаторы фрагментов) и / или? (параметры запроса) в конце URL, который оба эти решения (неверно) будут рассматривать как часть расширения файла.

Я обнаружил, что это был надежный способ использования pathinfo()URL-адреса после первого его анализа, чтобы удалить ненужный беспорядок после расширения файла:

$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

Использование substr($path, strrpos($path,'.')+1);. Это самый быстрый метод из всех сравнений.

@ Курт Чжун уже ответил.

Давайте проверим сравнительный результат здесь: https://eval.in/661574


2

Вы можете получить все расширения файлов в определенной папке и выполнять операции с определенным расширением файла:

<?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

Делай это быстрее.

Звонки на низком уровне должны быть очень быстрыми, поэтому я подумал, что это стоит того, чтобы провести исследование. Я попробовал несколько методов (с различной длиной строки, длиной расширения, несколькими прогонами каждый), вот несколько разумных:

function method1($s) {return preg_replace("/.*\./","",$s);} // edge case problem
function method2($s) {preg_match("/\.([^\.]+)$/",$s,$a);return $a[1];}
function method3($s) {$n = strrpos($s,"."); if($n===false) return "";return substr($s,$n+1);}
function method4($s) {$a = explode(".",$s);$n = count($a); if($n==1) return "";return $a[$n-1];}
function method5($s) {return pathinfo($s, PATHINFO_EXTENSION);}

Результаты были не очень удивительными. Плохой pathinfo(безусловно!) Самый медленный (похоже, он пытается разобрать все это, а затем отбросить все ненужные части) - и method3()(strrpos) самый быстрый, безусловно:

Original filename was: something.that.contains.dots.txt
Running 50 passes with 10000 iterations each
Minimum of measured times per pass:

    Method 1:   312.6 mike  (response: txt) // preg_replace
    Method 2:   472.9 mike  (response: txt) // preg_match
    Method 3:   167.8 mike  (response: txt) // strrpos
    Method 4:   340.3 mike  (response: txt) // explode
    Method 5:  2311.1 mike  (response: txt) // pathinfo  <--------- poor fella

ПРИМЕЧАНИЕ: первый метод имеет побочный эффект: он возвращает полное имя, когда нет расширения. Конечно, не имеет смысла измерять это дополнительными strpos, чтобы избежать такого поведения.

Вывод

Это похоже на Путь Самурая:

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

1

Если вы ищете скорость (например, в маршрутизаторе), вы, вероятно, не хотите, чтобы все токенизировались. Многие другие ответы не удастся с/root/my.folder/my.css

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

1

Хотя «лучший способ» является дискуссионным, я считаю, что это лучший способ по нескольким причинам:

function getExt($path)
{
    $basename = basename($path);
    return substr($basename, strlen(explode('.', $basename)[0]) + 1);
}
  1. Он работает с несколькими частями расширения, например tar.gz
  2. Короткий и эффективный код
  3. Работает как с именем файла, так и с полным путем

1

IMO, это лучший способ, если у вас есть имена файлов, такие как name.name.name.ext (некрасиво, но иногда бывает):

$ext     = explode('.', $filename); // Explode the string
$ext_len = count($ext) - 1; // Count the array -1 (because count() starts from 1)
$my_ext  = $ext[$ext_len]; // Get the last entry of the array

echo $my_ext;

1

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

Подход preg_replace мы используем поиск и замену регулярного выражения. В функции preg_replace первый параметр - это шаблон для поиска, второй параметр $ 1 - это ссылка на все, что соответствует первому (. *), А третий параметр - имя файла.

Другой способ, мы также можем использовать strrpos, чтобы найти позицию последнего вхождения '.' в имени файла и увеличьте эту позицию на 1, чтобы она взорвала строку из (.)

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


0

На самом деле, я искал это.

<?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);

-1

использование

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

для быстрого поиска по расширению (если вы точно знаете, что имя вашего файла есть).

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.