Как проверить типы загружаемых файлов в PHP? - PullRequest
46 голосов
/ 22 ноября 2008

На сайте PHP единственная реальная проверка, которую они предлагают, - это использование is_uploaded_file() или move_uploaded_file(), здесь . Конечно, вы обычно не хотите, чтобы пользователь загружал файлы любого типа по разным причинам.

Из-за этого я часто использовал "строгую" проверку типов пантомимы. Конечно, это очень некорректно, потому что часто MIME-типы неверны, и пользователи не могут загрузить свой файл. Это также очень легко подделать и / или изменить. И вместе с тем каждый браузер и операционная система работают с ними по-разному.

Другой способ - проверить расширение, которое, конечно, изменить проще, чем mime-тип.

Если вам нужны только изображения, используйте что-то вроде getimagesize().

А как насчет других типов файлов? PDF-файлы, документы Word или файлы Excel? Или даже текстовые файлы?

Редактировать: Если у вас нет mime_content_type или Fileinfo , а система ("file -bi $ uploadedfile") выдает неправильный тип файла, какие еще варианты есть?

Ответы [ 6 ]

33 голосов
/ 22 ноября 2008

Взгляните на mime_content_type или Fileinfo . Это встроенные команды PHP для определения типа файла путем просмотра содержимого файла. Также проверьте комментарии на вышеупомянутых двух страницах, есть некоторые другие хорошие предложения.

Лично мне повезло, используя что-то, что по сути system("file -bi $uploadedfile"), но я не уверен, что это лучший метод.

14 голосов
/ 16 декабря 2008

ИМХО, все методы проверки MIME-типов бесполезны.

Скажем, у вас есть MIME-тип application/pdf. Стандартные методы пытаются найти что-то, похожее на заголовок PDF (%PDF- или что-то в этом роде), и они возвращают «Хорошо, похоже, это PDF-файл» в случае успеха. Но на самом деле это ничего не значит. Вы можете загрузить файл, содержащий только %PDF-1.4, и он пройдет MIME-проверку.

Я имею в виду, если файл имеет ожидаемый MIME-тип - он всегда пройдет проверку MIME-типа, в противном случае результат не определен.

2 голосов
/ 20 июня 2014
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...";
    }
}
2 голосов
/ 19 марта 2012

Я использовал mime_content_type, который совместим с PHP 5.2, потому что я не могу использовать ни 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

2 голосов
/ 22 ноября 2008

Я предполагаю, что у вас будет фиксированный белый список типов файлов, которые вы примете.

Для каждого из этих типов вам придется использовать разные методы, чтобы убедиться, что они являются допустимыми примерами этого формата.

Есть два связанных вопроса:

  • Это выглядит примерно так, как будто это правильный тип? (Для JPEG вы можете проверить заголовки, как вы упомянули. Для многих форматов на основе Unix вы можете проверить «волшебный cookie».)

  • Действительно ли это допустимый пример этого типа (например, для любого XML-подобного формата вы можете проверить соответствие DTD.)

Я думаю, что для каждого формата вам следует задавать отдельные вопросы для каждого из них, потому что для PDF-файлов ответ будет отличаться от формата ZIP.

1 голос
/ 27 июня 2013

Вот функция 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, '; '));
}
...