2012-05-04 176 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>