Làm thế nào để tôi có được một phần mở rộng tập tin trong PHP?


723

Đây là một câu hỏi bạn có thể đọc ở mọi nơi trên web với nhiều câu trả lời khác nhau:

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

Vân vân.

Tuy nhiên, luôn có "cách tốt nhất" và nó nên có trên Stack Overflow.


15
Nguồn câu hỏi và câu trả lời: cowburn.info/2008/01/13/get-file-extension-comparison
salebar

5
Một cách khác để có được ext làstrrchr($filename, '.');
Verybadorms

Câu trả lời:


1776

Mọi người từ các ngôn ngữ kịch bản lệnh khác luôn nghĩ rằng ngôn ngữ của họ tốt hơn bởi vì họ có chức năng tích hợp sẵn để làm điều đó chứ không phải PHP (Tôi đang xem Pythonistas ngay bây giờ :-)).

Trong thực tế, nó tồn tại, nhưng ít người biết đến nó. Gặp gỡ pathinfo():

$ext = pathinfo($filename, PATHINFO_EXTENSION);

Điều này là nhanh chóng và tích hợp. pathinfo()có thể cung cấp cho bạn thông tin khác, chẳng hạn như đường dẫn chính tắc, tùy thuộc vào hằng số bạn truyền cho nó.

Hãy nhớ rằng nếu bạn muốn có thể xử lý các ký tự không phải ASCII, bạn cần đặt ngôn ngữ trước. VÍ DỤ:

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

Ngoài ra, lưu ý rằng điều này không xem xét nội dung tệp hoặc loại mime, bạn chỉ nhận được phần mở rộng. Nhưng đó là những gì bạn yêu cầu.

Cuối cùng, lưu ý rằng điều này chỉ hoạt động đối với đường dẫn tệp, không phải đường dẫn tài nguyên URL, được bao phủ bằng PARSE_URL.

Thưởng thức


62
Tôi ước tôi có thể bỏ phiếu này lên hai lần. Tôi không thể cho bạn biết tôi đã có thể thay thế bao nhiêu mã bằng cách sử dụng pathinfo
Mark Biek

8
Tôi cũng vậy, đó là lý do tại sao tôi đặt nó ở đây!
e-satis

7
Whaddaya biết, hóa ra có một cách tốt nhất.
Bến

19
@khizaransari Bạn nên tìm một nhà cung cấp dịch vụ lưu trữ khác, nhà cung cấp bạn nhận được là ngu ngốc. Thực sự, ý tôi là vậy Không có lý do gì để vô hiệu hóa chức năng này. Nói với họ rằng. Như một giải pháp thay thế: function get_ext($fname){ return substr($fname, strrpos($fname, ".") + 1); }Hãy chắc chắn rằng tệp có phần mở rộng, nó có thể làm bất cứ điều gì khi bạn vượt qua một đường dẫn làm đối số!
Lục

12
Bây giờ ý tưởng về PHP của tôi so với python đã thay đổi hoàn toàn khi tôi biết về chức năng này: O
Tommaso Barbugli

166

pathinfo()

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

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

14
Kể từ PHP 5.5 ->echo pathinfo('/foo/bar/baz.bill')['extension'];
Salman A

1
Điều này thậm chí hoạt động ở cấp độ này (Twitter json): $ ext = pathinfo ($ result-> Extended_entities-> media [0] -> video_info-> các biến thể [1] -> url, PATHINFO_EXTENSION);
KJS

100

URL ví dụ: http://example.com/myfolder/sympony.mp3?a=1&b=2#XYZ

A) Không sử dụng đề xuất không an toànPATHINFO :

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) Sử dụng 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'

THƯỞNG: Xem tất cả các ví dụ PHP gốc


3
Câu trả lời này bao gồm tất cả mọi thứ, ví dụ. một tập tin như thế foo_folder/foo-file.jpg?1345838509sẽ thất bại thảm hại chỉ với pathinfo, thanx

1
Không hoàn toàn về chủ đề, nhưng nó chắc chắn đã giải quyết vấn đề của tôi!
Howie

7
Đừng quên điều gì! parse_urldành cho URL và pathinfodành cho đường dẫn tệp.
Nabi KAZ

1
Bạn có ý nghĩa gì "quên thông tin đường dẫn"? Bạn sử dụng nó trong giải pháp!
Mùa thu Leonard

1
@AutumnLeonard Anh ấy không, anh ấy chỉ cho thấy sự khác biệt giữa pathinfo và parse_url.

59

Ngoài ra còn có SplFileInfo:

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

Thường thì bạn có thể viết mã tốt hơn nếu bạn truyền một đối tượng như vậy xung quanh thay vì một chuỗi. Mã của bạn đang nói nhiều hơn sau đó. Vì PHP 5.4, đây là một lớp lót:

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

Tuyệt vời, các đối tượng của nó đều đi xuống :)
Christopher Chase

2
Xin lưu ý rằng ->getExtension()có sẵn trong SplFileInfo kể từ PHP 5.3.6.
matthias

1
@matthias: Xin lưu ý rằng SPL có thể bị vô hiệu hóa trong các phiên bản PHP có trước phiên bản PHP 5.3.0. Nếu bạn vẫn không chạy PHP 5.3 nhưng 5.2 hoặc thấp hơn, câu trả lời này rất có thể không phù hợp với mã ổn định. Nếu không, bạn có thể ổn định mã của mình bằng cách yêu cầu một phiên bản PHP cụ thể và nếu không thì bảo lãnh.
hakre

@hakre Mặc dù bạn nói chính xác rằng "có thể bị vô hiệu hóa trong các phiên bản trước 5.3.0", tuy nhiên phần mở rộng SPL vẫn được biên dịch theo mặc định kể từ phiên bản PHP 5.0.0. Vì vậy, nhận xét này thực sự có ý nghĩa đối với những người bị buộc phải sử dụng PHP 5.2 trở xuống và không muốn từ chức bằng các lớp SPL cụ thể.
matthias

yeah, chỉ là phiên bản chết fluff :)
hakre

23

Phản hồi của E-satis là cách chính xác để xác định phần mở rộng tập tin.

Ngoài ra, thay vì dựa vào phần mở rộng tệp, bạn có thể sử dụng tệp infoinfo để xác định các tập tin Mime Type.

Đây là một ví dụ đơn giản về xử lý hình ảnh được tải lên bởi người dùng:

// 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
Đây là câu trả lời đúng CHỈ. Tôi không hiểu tại sao mọi người bỏ phiếu cho người khác. Vâng, cách tiếp cận này đòi hỏi nhiều nỗ lực hơn từ nhà phát triển nhưng nó giúp tăng hiệu suất (mặc dù ít, nhưng nó có). Hãy tham khảo điều này .
Bhasta Shah

2
@Bhasta: Trong một số trường hợp, chúng tôi có thể chỉ cần phần mở rộng tệp, họ về kiểm tra loại mime. Nhưng câu hỏi thực tế là về phần mở rộng tập tin, không phải loại tập tin. Vì vậy, đây KHÔNG phải là câu trả lời tốt nhất cho câu hỏi này. (chưa có câu trả lời)
Sasi varna kumar

chuyển đổi này cần một ngoặc thêm
rsb2097

16

Miễn là nó không chứa đường dẫn, bạn cũng có thể sử dụng:

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

Trong trường hợp $fnamelà một cái tên của tập tin, ví dụ: my_picture.jpg. Và kết quả sẽ là:jpg


@ Tại sao điều này có 3 downvote? nó cho kết quả thích hợp. Vui lòng giải thích
railsbox

Điều đó không sai, đó không phải là cách tốt nhất để làm điều đó. Nâng cao cho một chút cân bằng.

Đây là cách tốt nhất, khi bạn cần phần mở rộng thực và tên tệp có thể có nhiều. Trong đó, giống như người dùng đã tải ảnh lên trong trường hợp của tôi.
Rauli Rajande

2
Điều này không thành công nếu tên tệp không có phần mở rộng. Hãy thử chuyển qua "myfile" và nó sẽ trả về "myfile". Giá trị trả về đúng là một chuỗi rỗng dưới dạng phần mở rộng trong trường hợp sử dụng này.
pmont

Điều này là sai khi mảng_pop () sẽ đưa ra một thông báo vì nó lấy một con trỏ làm tham số của nó.
Nhím

12

1) Nếu bạn đang sử dụng (PHP 5> = 5.3.6), bạn có thể sử dụng SplFileInfo :: getExtension - Nhận phần mở rộng tệp

Mã ví dụ

<?php

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

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

?>

Điều này sẽ xuất

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

2) Một cách khác để nhận tiện ích mở rộng nếu bạn đang sử dụng (PHP 4> = 4.0.3, PHP 5)pathinfo

Mã ví dụ

<?php

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

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

?>

Điều này sẽ xuất

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

// EDIT: đã xóa một dấu ngoặc


12

Đôi khi nó không hữu ích để không sử dụng pathinfo($path, PATHINFO_EXTENSION). Ví dụ:

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

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

Cũng lưu ý rằng pathinfokhông thể xử lý một số ký tự không phải ASCII (thông thường nó chỉ loại bỏ chúng khỏi đầu ra). Trong các tiện ích mở rộng thường không phải là vấn đề, nhưng sẽ không đau khi biết về sự cảnh báo đó.


6
@ e-satis: Theo Wikipedia, chúng là hai phần mở rộng: Các hệ thống tệp giống như UNIX sử dụng một mô hình khác mà không có siêu dữ liệu mở rộng tách biệt. Ký tự dấu chấm chỉ là một ký tự khác trong tên tệp chính và tên tệp có thể có nhiều phần mở rộng, thường đại diện cho các phép biến đổi lồng nhau, chẳng hạn như files.tar.gz .
Alix Axel

1
Và nếu chúng ta có dấu chấm trong tên sản phẩm? Vd:test.19-02-2014.jpeg
Mario Radomanana

Điều này sẽ thất bại với /root/my.folder/my.css ltrim(strrchr($PATH, '.'),'.')hoạt động như pathinfo, nhưng không token hóa mọi thứ.
Ray Foss

8

Cách đơn giản nhất để có được phần mở rộng tệp trong PHP là sử dụng hàm pathinfo có sẵn của PHP .

$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

Bạn cũng có thể thử điều này (nó hoạt động trên PHP 5. * và 7):

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

Mẹo: nó trả về một chuỗi rỗng nếu tệp không có phần mở rộng


7

Xin lỗi ... "Câu hỏi ngắn; nhưng KHÔNG trả lời ngắn"

Ví dụ 1 cho 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);

Ví dụ 2 cho 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);

Đầu ra của ví dụ 1:

Name: base.min
Extension: css

Đầu ra của ví dụ 2:

Name: file.bak
Extension: php

Người giới thiệu

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

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

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


6

Một sửa chữa nhanh chóng sẽ là một cái gì đó như thế này.

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

Tại sao không chỉ sử dụng chức năng được xây dựng của php cho mục đích php.net/manual/en/feft.pathinfo.php thay vì sử dụng mã dài
Shahbaz

1
Bên cạnh quan điểm của Shahbaz, bạn cũng có thể $file_ext = end(explode('.', $filename));làm mọi thứ trong câu trả lời này trong một dòng thay vì bốn.
tvanc

@Amelia Nếu bạn có .tar.gz. Nó sẽ không hoạt động, vì vậy nếu bạn cần sử dụng đầy đủ tiện ích mở rộng, chẳng hạn như ltrim(strstr($filename, '.'), '.');để có đầy đủ tiện ích mở rộng thay vì không chính xác như gz.
Marin Sagovac

6

Đây là một ví dụ. Giả sử tên tệp $ là "example.txt",

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

Vì vậy, $ ext sẽ là ".txt".


6

pathinfo là một mảng. Chúng tôi có thể kiểm tra tên thư mục, tên tệp, phần mở rộng , v.v.:

$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
Điều này sẽ thất bại với /root/my.folder/my.css
Ray Foss

1
Điều này phải hoạt động chính xác: chất nền ($ path, strrpose ($ path, '.') + 1); Lưu ý: phương pháp này nhanh hơn bất kỳ giải pháp nào khác ở trên. Hãy thử một điểm chuẩn bằng cách sử dụng tập lệnh riêng của chúng tôi.
Abbas

4

Bạn cũng có thể thử điều này:

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

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

đây là cách tốt nhất nếu bạn có tên tệp như name.name.name.ext (xấu, nhưng đôi khi nó xảy ra


3

Điều này sẽ làm việc

$ext = pathinfo($filename, PATHINFO_EXTENSION);

Điều này đã được trả lời tốt hơn nhiều bởi Subodh trở lại vào tháng Tám.
Nisse Engström

3

Tôi thấy rằng các giải pháp pathinfo()SplFileInfohoạt động tốt cho các tệp tiêu chuẩn trên hệ thống tệp cục bộ, nhưng bạn có thể gặp khó khăn nếu bạn làm việc với các tệp từ xa vì URL cho hình ảnh hợp lệ có thể có #(số nhận dạng phân đoạn) và / hoặc? (tham số truy vấn) ở cuối URL, cả hai giải pháp đó sẽ (không chính xác) sẽ coi là một phần của phần mở rộng tệp.

Tôi thấy đây là một cách đáng tin cậy để sử dụng pathinfo()trên URL sau lần đầu tiên phân tích cú pháp để loại bỏ sự lộn xộn không cần thiết sau khi mở rộng tệp:

$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

Sử dụng substr($path, strrpos($path,'.')+1); . Đây là phương pháp nhanh nhất trong tất cả các so sánh.

@Kurt Zhong đã trả lời.

Hãy kiểm tra kết quả so sánh tại đây: https://eval.in/661574


2

Bạn có thể nhận được tất cả các phần mở rộng tệp trong một thư mục cụ thể và thực hiện các thao tác với phần mở rộng tệp cụ thể:

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

Làm cho nó nhanh hơn.

Các cuộc gọi cấp thấp cần phải rất nhanh vì vậy tôi nghĩ rằng nó đáng để nghiên cứu. Tôi đã thử một vài phương thức (với độ dài chuỗi khác nhau, độ dài mở rộng, nhiều lần chạy mỗi cái), đây là một số phương pháp hợp lý:

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

Kết quả không mấy ngạc nhiên. Tội nghiệp pathinfolà (cho đến nay!) Là chậm nhất (có vẻ như anh ta đang cố phân tích toàn bộ và sau đó bỏ tất cả các phần không cần thiết) - và method3()(strrpose) là nhanh nhất, cho đến nay:

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

LƯU Ý: phương thức đầu tiên có tác dụng phụ: nó trả về toàn bộ tên khi không có phần mở rộng. Chắc chắn sẽ không có ý nghĩa gì khi đo nó bằng một âm mưu bổ sung để tránh hành vi này.

Phần kết luận

Điều này trông giống như cách của Samurai:

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

1

Nếu bạn đang tìm kiếm tốc độ (chẳng hạn như trong bộ định tuyến), có lẽ bạn không muốn token hóa mọi thứ. Nhiều câu trả lời khác sẽ thất bại với/root/my.folder/my.css

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

1

Mặc dù "cách tốt nhất" vẫn còn gây tranh cãi, tôi tin rằng đây là cách tốt nhất vì một vài lý do:

function getExt($path)
{
    $basename = basename($path);
    return substr($basename, strlen(explode('.', $basename)[0]) + 1);
}
  1. Nó hoạt động với nhiều phần cho một phần mở rộng, ví dụ tar.gz
  2. Mã ngắn và hiệu quả
  3. Nó hoạt động với cả tên tệp và đường dẫn hoàn chỉnh

1

IMO, đây là cách tốt nhất nếu bạn có tên tệp như name.name.name.ext (xấu, nhưng đôi khi nó xảy ra):

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

phương pháp tiếp cận preg numplace chúng tôi sử dụng tìm kiếm biểu thức chính quy và thay thế. Trong hàm preg numplace, tham số đầu tiên là mẫu cho tìm kiếm, tham số thứ hai $ 1 là tham chiếu đến bất cứ thứ gì khớp với tham số thứ nhất (. *) Và thứ ba là tên tệp.

Một cách khác, chúng ta cũng có thể sử dụng strrpose để tìm vị trí xuất hiện cuối cùng của một '.' trong một tên tệp và tăng vị trí đó lên 1 để nó sẽ phát nổ chuỗi từ (.)

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


0

Thật ra, tôi đang tìm kiếm điều đó.

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

Sử dụng

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

để truy xuất tiện ích mở rộng nhanh (nếu bạn biết chắc chắn tên tệp của mình có tên).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.