2012-05-04 254 views
33

我檢查文件擴展名是否上傳。我的方法工作,但現在我需要明白,我的方法(pathinfo)是真的嗎?另一種更好更快的方式?!由於php檢查文件擴展名爲

$filename = $_FILES['video_file']['name']; 
$ext = pathinfo($filename, PATHINFO_EXTENSION); 
if($ext !== 'gif' || $ext !== 'png' || $ext !== 'jpg') {echo 'error';} 
+10

爲什麼這個字段名爲'video_file',但你只允許圖像.. – cream

+2

我發現這個問題尋找有效的文件擴展名。我在這裏沒有回答這個問題,但我想指出你在if語句中有一個邏輯錯誤。它必須是條件之間的'&&'而不是'||'......只是想我會分享我的觀點。 – itsols

回答

94

使用if($ext !== 'gif')可能不是有效的,如果你允許什麼樣的20個不同的擴展

嘗試

$allowed = array('gif','png' ,'jpg'); 
$filename = $_FILES['video_file']['name']; 
$ext = pathinfo($filename, PATHINFO_EXTENSION); 
if(!in_array($ext,$allowed)) { 
    echo 'error'; 
} 
+0

我正在上傳一個文件名與大寫(DOG.JPG),所以我不得不添加$ filename = strtolower($文件名); – Mikeys4u

+0

@Baba先生您好,先生,我們如何在多文件上傳中做到這一點。 我也得到$ ext的錯誤,這意味着我無法從這段代碼中獲得我的文件擴展名。我該怎麼辦? –

37

檢查的文件擴展名不被認爲是最好的做法,完成這個任務的首選方法是通過檢查文件mime type

從PHP:

<?php 
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type 
foreach (glob("*") as $filename) { 
    echo finfo_file($finfo, $filename) . "\n"; 
} 
finfo_close($finfo); 
?> 

上面的示例將相似的輸出的東西,你應該檢查。

text/html 
image/gif 
application/vnd.ms-excel 

雖然MIME類型也可以被欺騙(編輯文件的前幾個字節,並修改幻數),但它比編輯的文件名困難。所以你永遠無法100%確定該文件類型的實際內容,並且應該注意處理由用戶上傳/通過電子郵件發送的文件。

+2

我幾乎懷疑有一種方法可以獲得REAL文件擴展名。到處都有答案「分析文件名」這是最糟糕的方式......非常感謝這個答案! – instead

+1

這個答案應該在頂部,對於有人來說很容易改變文件擴展名! –

+0

如果MIME是假的,你會建議什麼?惡意用戶可以使用腳本或其他允許發送HTTP POST請求的自動應用程序輕鬆上傳文件,這允許他發送假的MIME類型。 –

10

就個人而言,我更喜歡使用preg_match()功能:如果你有很多擴展的驗證和性能比較問題

if(preg_match("/\.(gif|png|jpg)$/", $filename)) 

in_array()

$exts = array('gif', 'png', 'jpg'); 
if(in_array(end(explode('.', $filename)), $exts) 

隨着in_array()可能是有用的。 驗證文件圖像的另一種方法:如果函數失敗,則可以使用@imagecreatefrom*(),這表示圖像無效。

例如:

function testimage($path) 
{ 
    if(!preg_match("/\.(png|jpg|gif)$/",$path,$ext)) return 0; 
    $ret = null; 
    switch($ext) 
    { 
     case 'png': $ret = @imagecreatefrompng($path); break; 
     case 'jpeg': $ret = @imagecreatefromjpeg($path); break; 
     // ... 
     default: $ret = 0; 
    } 

    return $ret; 
} 

然後:

$valid = testimage('foo.png'); 

假設foo.png.png擴展PHP腳本文件,上述功能失效。它可以避免像shell更新和LFI這樣的攻擊。

5

PATHINFO是很酷,但你的代碼可以改進:

$filename = $_FILES['video_file']['name']; 
$ext = pathinfo($filename, PATHINFO_EXTENSION); 
$allowed = array('jpg','png','gif'); 
if(! in_array($ext, $allowed)) {echo 'error';} 

當然只要檢查文件名的擴展名就不能保證文件類型爲有效圖像。您可以考慮使用像getimagesize這樣的功能來驗證上傳的圖像文件。

2

不知道這是否會具有更快的計算時間,但另一種選擇......

$acceptedFormats = array('gif', 'png', 'jpg'); 

if(!in_array(pathinfo($filename, PATHINFO_EXTENSION), $acceptedFormats))) { 
    echo 'error'; 
} 
2

文件類型可以在其他方面也進行檢查。我相信這是檢查上傳文件類型的最簡單方法..如果你正在處理一個圖像文件,然後去下面的代碼。如果你正在處理一個視頻文件,然後替換與視頻檢查圖像檢查中,如果塊..樂趣

 
    $img_up = $_FILES['video_file']['type']; 
$img_up_type = explode("/", $img_up); 
$img_up_type_firstpart = $img_up_type[0];

if($img_up_type_firstpart == "image") { // image is the image file type, you can deal with video if you need to check video file type

/* do your logical code */ }

+0

$ _FILES ['field_name'] ['type']是用戶定義的,因此不應該依賴驗證。您應該使用php的exif_imagetype或getimagesize函數來檢查圖像的細節/類型。 – dading84

-2

使用此功能

function check_image_extension($image){ 

     $images_extentions = array("jpg","JPG","jpeg","JPEG","png","PNG"); 

     $image_parts = explode(".",$image); 

     $image_end_part = end($image_parts); 

     if(in_array($image_end_part,$images_extentions) == true){ 

      return time() . "." . $image_end_part; 


     }else{ 

      return false; 
     } 


    } 
1

我認爲這可能會爲你工作

//<?php 
    //checks file extension for images only 
    $allowed = array('gif','png' ,'jpg'); 
    $file = $_FILES['file']['name']; 
    $ext = pathinfo($file, PATHINFO_EXTENSION); 
     if(!in_array($ext,$allowed)) 
      { 
//?> 
<script> 
     alert('file extension not allowed'); 
     window.location.href='some_link.php?file_type_not_allowed_error'; 
</script> 

//<?php 
exit(0); 
    } 
//?> 
0

要正確地實現這一點,最好通過檢查MIME類型。

function get_mime($file) { 
    if (function_exists("finfo_file")) { 
    $finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension 
    $mime = finfo_file($finfo, $file); 
    finfo_close($finfo); 
    return $mime; 
    } else if (function_exists("mime_content_type")) { 
    return mime_content_type($file); 
    } else if (!stristr(ini_get("disable_functions"), "shell_exec")) { 
    // http://stackoverflow.com/a/134930/1593459 
    $file = escapeshellarg($file); 
    $mime = shell_exec("file -bi " . $file); 
    return $mime; 
    } else { 
    return false; 
    } 
} 
//pass the file name as 
echo(get_mime($_FILES['file_name']['tmp_name'])); 
0

如何在上載之前驗證表單上的文件擴展名(僅限jpg/jpeg)。另一個發佈的答案的變體與一個包含的數據過濾器在評估其他發佈的表單值時可能有用。注意:如果爲空,則錯誤留空,因爲這是我的用戶的選項,而不是要求。

<?php 
if(isset($_POST['save'])) { 

//Validate image 
if (empty($_POST["image"])) { 
$imageError = ""; 
} else { 
$image = test_input($_POST["image"]); 
$allowed = array('jpeg','jpg'); 
$ext = pathinfo($image, PATHINFO_EXTENSION); 
if(!in_array($ext,$allowed)) { 
$imageError = "jpeg only"; 
} 
} 

} 

// Validate data 
function test_input($data) { 
$data = trim($data); 
$data = stripslashes($data); 
$data = htmlspecialchars($data); 
return $data; 
} 
<? 

您的html看起來像這樣;

<html> 
<head> 
</head> 

<body> 
<!-- Validate --> 
<?php include_once ('validate.php'); ?> 

<!-- Form --> 
<form method="post" action=""> 

<!-- Image --> 
<p>Image <?php echo $imageError; ?></p> 
<input type="file" name="image" value="<?php echo $image; ?>" /> 

<p><input type="submit" name="save" value="SAVE" /></p> 
</form> 

</body> 
</html>