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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/310714/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 22:20:52  来源:igfitidea点击:

How to check file types of uploaded files in PHP?

phpvalidationfile-uploadmime-types

提问by Darryl Hein

On the PHP website, the only real checking they suggest is using is_uploaded_file()or move_uploaded_file(), here. Of course you usually don't want user's uploading any type of file, for a variety of reasons.

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

Because of this, I have often used some "strict" mime type checking. Of course this is very flawed because often mime types are wrong and users can't upload their file. It is also very easy to fake and/or change. And along with all of that, each browser and OS deals with them differently.

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

Another method is to check the extension, which of course is even easier to change than mime type.

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

If you only want images, using something like getimagesize()will work.

如果你只想要图像,使用类似的东西getimagesize()会起作用。

What about other types of files? PDFs, Word documents or Excel files? Or even text only files?

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

Edit:If you don't have mime_content_typeor Fileinfoand system("file -bi $uploadedfile") gives you the wrong file type, what other options are there?

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

采纳答案by davr

Take a look at mime_content_typeor Fileinfo. These are built-in PHP commands for determining the type of a file by looking at the contents of the file. Also check the comments on the above two pages, there are some other good suggestions.

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

Personally I've had good luck using something that's essentially system("file -bi $uploadedfile"), but I'm not sure if that's the best method.

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

回答by Sudden Def

IMHO, all MIME-type checking methods are useless.

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

Say you've got which should have MIME-type application/pdf. Standard methods are trying to find something that looks like a PDF header (%PDF-or smth. like that) and they will return 'Okay, seems like this is a PDF file' on success. But in fact this doesn't means anything. You can upload a file containing only %PDF-1.4and it will pass MIME-check.

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

I mean if the file has an expected MIME-type - it will always pass the MIME-type check otherwise the result is undefined.

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

回答by Francesco Galgani

I used mime_content_type that is compatible with PHP 5.2, because I can use neither Fileinfo(it requires PHP 5.3) nor system(), that is disabled by my provider. For example, I check if a file is a text file so:

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

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

You can see a full example in my "PHP Directory and Subdirectory Listener & File Viewer and Downloader" at: http://www.galgani.it/software_repository/index.php

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

回答by Oddthinking

I assume you are going to have a fixed white-list of file-types that you will accept.

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

For each of these types, you are going to have to use different techniques to verify that they are valid examples of that format.

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

There are two related questions:

有两个相关的问题:

  • Does it look roughly like it might be the right type? (For JPEG, you could check the headers, as you mentioned. For many Unix-based formats, you could check the "magic cookie".)

  • Is it actually a valid example of that type (e.g. For any XML-like format, you could validate against a DTD.)

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

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

I think that, for each format, you should ask separate questions for each one, because the answer will be quite different for PDFs compared to ZIP files.

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

回答by Krausz Lóránt Szilveszter

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...";
    }
}

回答by iZend

Here is the function file_mime_typefrom iZend:

这是file_mime_typeiZend的函数:

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

回答by Kris Roofe

For PHP>=5.3.0, you can use php's finfo_file(finfo_file) function to get the file infomation about the file.

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

For PHP<5.3.0, you can use your's system's filecommand to get the file information.

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

So just make it in one function,

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

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

MimeTypes

MimeTypes