49

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

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

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

如果你只想要图像,使用类似的东西getimagesize()就可以了。

其他类型的文件呢?PDF、Word 文档或 Excel 文件?甚至是纯文本文件?

编辑:如果您没有mime_content_typeFileinfo并且 system("file -bi $uploadedfile") 给您错误的文件类型,还有哪些其他选项?

4

7 回答 7

33

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

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

于 2008-11-22T02:13:09.677 回答
15

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

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

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

于 2008-12-16T07:54:04.160 回答
2

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

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

有两个相关的问题:

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

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

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

于 2008-11-22T02:03:37.637 回答
2

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

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

你可以在我的“PHP Directory and Subdirectory Listener & File Viewer and Downloader”中看到一个完整的例子: http ://www.galgani.it/software_repository/index.php

于 2012-03-18T23:47:51.610 回答
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...";
    }
}
于 2014-06-20T13:10:04.570 回答
1

这是file_mime_type来自 iZend 的函数:

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, '; '));
}
于 2013-06-27T17:17:54.333 回答
0

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

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

所以只需在一个函数中实现,

var_dump(mime_type("wiki templete.txt"));   // print string(10) "text/plain"

function mime_type($file_path)
{
    if (function_exists('finfo_open')) {
        $finfo = new finfo(FILEINFO_MIME_TYPE, null);
        $mime_type = $finfo->file($file_path);
    }
    if (!$mime_type && function_exists('passthru') && function_exists('escapeshellarg')) {
        ob_start();
        passthru(sprintf('file -b --mime %s 2>/dev/null', escapeshellarg($file_path)), $return);
        if ($return > 0) {
            ob_end_clean();
            $mime_type = null;
        }
        $type = trim(ob_get_clean());
        if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\.]+)#i', $type, $match)) {
            $mime_type = null;
        }
        $mime_type = $match[1];
    }
    return $mime_type;
}

哑剧类型

于 2019-08-10T06:16:47.633 回答