如何在PHP中检查上传文件的文件类型?

时间:2008-11-22 01:49:58

标签: php validation file-upload mime-types

在PHP网站上,他们建议的唯一真实检查是使用is_uploaded_file()move_uploaded_file()here。当然,出于各种原因,您通常不希望用户上传任何类型的文件。

因此,我经常使用一些“严格”的mime类型检查。当然这是非常有缺陷的,因为mime类型通常是错误的,用户无法上传他们的文件。伪造和/或改变也很容易。除此之外,每个浏览器和操作系统都以不同的方式处理它们。

另一种方法是检查扩展名,当然比mime类型更容易改变。

如果您只想要图片,请使用getimagesize()之类的内容。

其他类型的文件怎么样? PDF,Word文档或Excel文件?甚至是纯文本文件?

修改:如果您没有mime_content_typeFileinfo而系统(“文件-bi $ uploadedfile”)为您提供了错误的文件类型,还有哪些其他选项在那里?

7 个答案:

答案 0 :(得分:33)

查看mime_content_typeFileinfo。这些是内置的PHP命令,用于通过查看文件的内容来确定文件的类型。另外还要检查上面两页的评论,还有一些其他好的建议。

我个人幸运地使用了基本上system("file -bi $uploadedfile")的东西,但我不确定这是不是最好的方法。

答案 1 :(得分:14)

恕我直言,所有MIME类型的检查方法都没用。

假设您应该拥有MIME类型application/pdf。标准方法试图找到看起来像PDF标题(%PDF-或smth。之类的东西)并且它们将成功返回'好吧,好像这是一个PDF文件'。但实际上这并不意味着什么。您可以上传仅包含%PDF-1.4的文件,它将通过MIME检查。

我的意思是如果文件具有预期的MIME类型 - 它将始终传递MIME类型检查,否则结果是未定义的。

答案 2 :(得分:2)

我假设您将拥有一个固定的文件类型白名单,您将接受。

对于每种类型,您将不得不使用不同的技术来验证它们是该格式的有效示例。

有两个相关的问题:

  • 它看起来大致可能是正确的类型吗? (对于JPEG,您可以检查标题,正如您所提到的。对于许多基于Unix的格式,您可以检查“魔术cookie”。)

  • 它实际上是该类型的有效示例(例如,对于任何类似XML的格式,您可以针对DTD进行验证。)

我认为,对于每种格式,您应该为每种格式提出单独的问题,因为与ZIP文件相比,PDF的答案会有很大差异。

答案 3 :(得分:2)

我使用了与PHP 5.2兼容的mime_content_type,因为我既不能使用Fileinfo(它需要PHP 5.3),也不能使用system(),我的提供者禁用了它。 例如,我检查文件是否是文本文件,所以:

if (strcmp(substr(mime_content_type($f),0,4),"text")==0) { ... }

您可以在我的“PHP目录和子目录监听器&文件查看器和下载器”中查看完整示例: http://www.galgani.it/software_repository/index.php

答案 4 :(得分:2)

if(isset($_FILES['uploaded'])) {
    $temp = explode(".", $_FILES["uploaded"]["name"]);

    $allowedExts = array("txt","htm","html","php","css","js","json","xml","swf","flv","pdf","psd","ai","eps","eps","ps","doc","rtf","ppt","odt","ods");

    $extension = end($temp);
    if( in_array($extension, $allowedExts)) {
       //code....

    } else {
        echo "Error,not Documentum type...";
    }
}

答案 5 :(得分:1)

以下是来自iZend的函数file_mime_type

function file_mime_type($file, $encoding=true) {
    $mime=false;

    if (function_exists('finfo_file')) {
        $finfo = finfo_open(FILEINFO_MIME);
        $mime = finfo_file($finfo, $file);
        finfo_close($finfo);
    }
    else if (substr(PHP_OS, 0, 3) == 'WIN') {
        $mime = mime_content_type($file);
    }
    else {
        $file = escapeshellarg($file);
        $cmd = "file -iL $file";

        exec($cmd, $output, $r);

        if ($r == 0) {
            $mime = substr($output[0], strpos($output[0], ': ')+2);
        }
    }

    if (!$mime) {
        return false;
    }

    if ($encoding) {
        return $mime;
    }

    return substr($mime, 0, strpos($mime, '; '));
}

答案 6 :(得分:0)

对于PHP> = 5.3.0,您可以使用php的killPromisefinfo_file)函数来获取有关文件的文件信息。

对于PHP <5.3.0,您可以使用系统的finfo_file命令来获取文件信息。

所以只需将其设置为一个函数,

file

MimeTypes