Подтвердить что ты не робот

Как проверить, является ли загруженный файл изображением без типа mime?

Я хочу проверить, является ли загруженный файл файлом изображения (например, png, jpg, jpeg, gif, bmp) или другим файлом. Проблема в том, что я использую Uploadify для загрузки файлов, что изменяет тип mime и дает "text/octal" или что-то вроде типа mime, независимо от того, какой тип файла вы загружаете.

Есть ли способ проверить, является ли загруженный файл изображением отдельно от проверки расширения файла с помощью PHP?

4b9b3361

Ответ 1

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

Ответ 2

Моя мысль о предмете проста: все загруженные изображения злы.

И не только потому, что они могут содержать вредоносные коды, но особенно из-за мета-тегов. Я знаю о сканерах, которые просматривают веб-страницы, чтобы найти защищенные изображения, используя свои скрытые метатеги, а затем играть с их авторскими правами. Возможно, немного параноидально, но поскольку загруженные пользователем изображения не контролируют проблемы авторского права, я принимаю это во внимание.

Чтобы избавиться от этих проблем, я систематически конвертирую все загруженные изображения в png с помощью gd. У этого есть много преимуществ: изображение чиста от возможных вредоносных кодов и мета-тегов, у меня есть только один формат для всех загруженных изображений, я могу настроить размер изображения в соответствии со своим стандартом и... Я сразу же знаю если изображение верное или нет! Если изображение невозможно открыть для преобразования (используя imagecreatefromstring, который не уход за форматом изображения), то я считаю изображение недействительным.

Простая реализация может выглядеть так:

function imageUploaded($source, $target)
{
   // check for image size (see @DaveRandom comment)
   $size = getimagesize($source);
   if ($size === false) {
      throw new Exception("{$source}: Invalid image.");
   }
   if ($size[0] > 2000 || $size[1] > 2000) {
      throw new Exception("{$source}: Too large.");
   }

   // loads it and convert it to png
   $sourceImg = @imagecreatefromstring(@file_get_contents($source));
   if ($sourceImg === false) {
      throw new Exception("{$source}: Invalid image.");
   }
   $width = imagesx($sourceImg);
   $height = imagesy($sourceImg);
   $targetImg = imagecreatetruecolor($width, $height);
   imagecopy($targetImg, $sourceImg, 0, 0, 0, 0, $width, $height);
   imagedestroy($sourceImg);
   imagepng($targetImg, $target);
   imagedestroy($targetImg);
}

Чтобы проверить это:

header('Content-type: image/png');
imageUploaded('http://www.dogsdata.com/wp-content/uploads/2012/03/Companion-Yellow-dog.jpg', 'php://output');

Это точно не отвечает на ваш вопрос, поскольку это такой же взлом, как и принятый ответ, но я даю вам свои причины для его использования, по крайней мере: -)

Ответ 3

Вы можете проверить тип изображения, проверив магические числа в начале файла.

Например: каждый файл JPEG начинается с блока "FF D8 FF E0" .

Подробнее о магических номерах

Ответ 4

Если Uploadify действительно изменяет тип mime - я считаю это ошибкой. Это не имеет никакого смысла, поскольку это блокирует разработчиков от работы с Функции на основе mime-типа в PHP:

Это небольшая вспомогательная функция, которая возвращает тип mime на основе первых 6 байтов файла.

/**
 * Returns the image mime-type based on the first 6 bytes of a file
 * It defaults to "application/octet-stream".
 * It returns false, if problem with file or empty file.
 *
 * @param string $file 
 * @return string Mime-Type
 */
function isImage($file)
{
    $fh = fopen($file,'rb');
    if ($fh) { 
        $bytes = fread($fh, 6); // read 6 bytes
        fclose($fh);            // close file

        if ($bytes === false) { // bytes there?
            return false;
        }

        // ok, bytes there, lets compare....

        if (substr($bytes,0,3) == "\xff\xd8\xff") { 
            return 'image/jpeg';
        }
        if ($bytes == "\x89PNG\x0d\x0a") { 
            return 'image/png';
        }
        if ($bytes == "GIF87a" or $bytes == "GIF89a") { 
            return 'image/gif';
        }

        return 'application/octet-stream';
    }
    return false;
}

Ответ 5

Вы можете проверить первые несколько байтов файла для магического номера, чтобы определить формат изображения.

Ответ 6

Попробуйте использовать exif_imagetype для получения фактического типа изображения. Если файл слишком мал, он выдаст ошибку, и если он не сможет найти его, он вернет false

Ответ 7

Невозможно ли допросить файл с помощью finfo_file?

$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimetype = finfo_file($finfo, $filename); //should contain mime-type
finfo_close($finfo);

Этот ответ не проверен, но основан на этом обсуждении форума на форумах Uploadify.

Я также хотел бы указать, что finfo должен "попытаться угадать тип содержимого и кодировку файла, ища определенные последовательности байт-байт в определенных положениях в пределах file" , поэтому, по моему мнению, это все равно должно работать, даже если в программе Uploaded указан неправильный тип mime.