Проверьте тип и размер файла изображения перед загрузкой файла в php - PullRequest
5 голосов
/ 09 августа 2009

У меня есть следующий код:

$filecheck = basename($_FILES['imagefile']['name']);
  $ext = substr($filecheck, strrpos($filecheck, '.') + 1);
  if (($ext == "jpg" || $ext == "gif" || $ext == "png") && ($_FILES["imagefile"]["type"] == "image/jpeg" || $_FILES["imagefile"]["type"] == "image/gif" || $_FILES["imagefile"]["type"] == "image/png") && 
    ($_FILES["imagefile"]["size"] < 2120000)){
} else {
echo "F2";
die();
}

Что мне нужно сделать, это проверить, является ли загруженный файл jpg / gif / png и что его размер составляет менее 2 мегабайт.

Если его размер превышает 2 мегабайта, или файл неправильного типа, мне нужно вернуть / echo F2 (код ошибки для API).

Когда я использую код выше для обработки файла JPG 70 КБ, он возвращает F2.

SUBNOTE картинка, которую я загружаю, имеет расширение .JPG. Может ли дело быть фактором? Если да, то как мне приспособиться к этому?

Ответы [ 7 ]

22 голосов
/ 09 августа 2009

Обратите внимание, что вы не можете полагаться на расширения файлов для определения типа файла. Для кого-то было бы довольно легко, например, загрузить исполняемый файл с расширением .png. MIME-тип также может быть легко подделан вредоносным клиентом для передачи в виде изображения. Использование этой информации представляет собой угрозу безопасности .

Документация PHP :
Тип файла MIME, если браузер предоставил эту информацию. Примером может быть «image / gif». Этот тип MIME, однако, не проверяется на стороне PHP, и поэтому не принимает его значение как должное .

Попробуйте загрузить изображения с помощью gd (getimagesize()), чтобы убедиться, что они действительно являются допустимыми изображениями (а не просто случайными файлами с заголовком файла изображения ... finfo_file опирается на эти заголовки).

if($_FILES["imagefile"]["size"] >= 2120000) {
  echo "F2";
  die();
} else {
    $imageData = @getimagesize($_FILES["imagefile"]["tmp_name"]);

    if($imageData === FALSE || !($imageData[2] == IMAGETYPE_GIF || $imageData[2] == IMAGETYPE_JPEG || $imageData[2] == IMAGETYPE_PNG)) {
      echo "F2";
      die();
    }
}

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

$filecheck = basename($_FILES['imagefile']['name']);
$ext = strtolower(substr($filecheck, strrpos($filecheck, '.') + 1));

if (!(($ext == "jpg" || $ext == "gif" || $ext == "png") && ($_FILES["imagefile"]["type"] == "image/jpeg" || $_FILES["imagefile"]["type"] == "image/gif" || $_FILES["imagefile"]["type"] == "image/png") && 
    ($_FILES["imagefile"]["size"] < 2120000))){
    echo "F2";
    die();
}
5 голосов
/ 09 августа 2009

Сравнения типа $ext == "jpg" только проверяют, что $ext точно "jpg".

Возможно, вы захотите использовать strtolower на $ ext перед выполнением этих сравнений, чтобы справиться с ситуацией ".JPG".


Если вы используете PHP <= 5.2, вы можете использовать <a href="http://fr.php.net/manual/en/function.mime-content-type.php" rel="noreferrer"> mime_content_type для проверки типа содержимого файлов вместо того, чтобы полагаться на $_FILES['imagefile']['name'] и / или $_FILES["imagefile"]["type"], которые оба отправляются клиент - и, как таковой, может быть подделан.

Если вы используете PHP> = 5.3, вы можете рассмотреть новое расширение fileinfo , и оно finfo_file function


Для размера файла вы уже используете $_FILES["imagefile"]["size"]; это нормально, я думаю, но вы узнаете об этом только после загрузки файла - тем не менее, я боюсь, что нет реального способа проверить подобные вещи перед загрузкой ...


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

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

Некоторые браузеры могут поддерживать скрытое поле с именем MAX_FILE_SIZE (см. Документацию о загрузка файла ); но не уверен, что он действительно поддерживается (никогда не видел, чтобы он использовался, на самом деле; так, вероятно, нет :-()


В качестве sidenote вы, вероятно, захотите настроить upload_max_filesize , чтобы он позволял загружать файлы по крайней мере настолько большого размера, насколько вы хотите (по умолчанию он обычно равен 2 МБ; поэтому он уже должен быть в порядке)

5 голосов
/ 09 августа 2009

ОТПРАВИТЬ изображение, которое он загружает, имеет расширение .JPG. Может ли дело быть фактором? Если да, то как мне приспособиться к этому?

Да, это проблема. Вы должны добавить strtolower () к этой строке:

$ext = substr($filecheck, strrpos($filecheck, '.') + 1);

как:

$ ext = strtolower (substr ($ filecheck, strrpos ($ filecheck, '.') + 1));

Это исправит вашу текущую проблему. Но технически вам не нужно беспокоиться о расширениях файлов, вам действительно нужно только проверить тип MIME

3 голосов
/ 11 августа 2009

Размер файла довольно очевиден, но то, что люди делают выше, чтобы проверить, что это правильный формат, несколько неэффективно и "небезопасно".

Вот что я делаю:

if($_FILES["userPicture"]["error"] == 0) {
// File was uploaded ok, so it's ok to proceed with the filetype check.
    $uploaded_type = exif_imagetype($_FILES["userPicture"]["tmp_name"]);
    // What we have now is a number representing our file type.

    switch($uploaded_type) {
        case "1":
            $uploaded_type = "gif";
        break;
        case "2":
            $uploaded_type = "jpg";
        break;
        case "3":
            $uploaded_type = "png";
        break;
    }
}

Больше информации на;
http://www.php.net/manual/en/function.exif-imagetype.php

Редактировать: Это имеет преимущество работы «в каждом браузере», потому что он не зависит от имени файла или от того, что предоставил пользователь, кроме значения массива файлов «ошибка», которое говорит нам, что на самом деле не было ошибки.

3 голосов
/ 09 августа 2009

обратите внимание, что для Internet Explorer они передают MIME-файл в формате JPEG как image / pjpeg - что отличается от других браузеров.

Вот простая функция, чтобы получить ваш тип пантомимы против расширения файла:

function mime2ext($mime){ // mime is like image/jpeg
    $m = explode('/',$mime);
    $mime = $m[count($m)-1]; // get the second part of the mime type
    switch($mime){
        case 'jpg':
        case 'jpeg':
        case 'pjpeg':
            return 'jpg';
            break;
        case 'png':
            return 'png';
            break;
        case 'gif':
            return 'gif';
            break;
    }
    return '';
}
2 голосов
/ 09 августа 2009

Вам нужно две вещи:

Сделайте ваш добавочный регистр нечувствительным к регистру:

if($strtolower($ext == "jpg")){
  // do your stuff
}

Проверьте, содержит ли файл изображение. Простой способ сделать это - fileinfo:

$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo finfo_file($finfo, $filename);
$finfo_close($finfo);

Альтернативный способ проверки того, является ли файл изображением, загружается в библиотеку изображений, такую ​​как gd. Если ваш файл может быть успешно загружен, это изображение.

Имейте в виду, что изображения в формате JPEG могут иметь расширение .jpg или .jpeg.

2 голосов
/ 09 августа 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...