Изменение размера изображения PHP и мой скрипт загрузки

Я видел много примеров, но не уверен, как это может быть связано с текущим сценарием загрузки. Не мог бы кто-нибудь объяснить, как я могу использовать ImageMagick или что-то в этом роде, чтобы изменить размер загруженного изображения до фиксированной ширины, сохраняя соотношение w: h?

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

// Include Extension finder function.
include_once 'find_extension.php';

    // Function Gathers the Input Name, Store Number and Picture Number. The picture number is assigned by the loop that will be cycling through the images to be uploaded. The store Number and the Picure Number will make the file name.
    function uploadImage($inputname, $storenum, $picturenum){

// A few parameters, to restrict file types and file size to 20kb.
if ((($_FILES[$inputname]["type"] == "image/gif")
|| ($_FILES[$inputname]["type"] == "image/png") 
|| ($_FILES[$inputname]["type"] == "image/jpeg") 
|| ($_FILES[$inputname]["type"] == "image/pjpeg"))
&& ($_FILES[$inputname]["size"] < 200000))
  {
      // If there is an error, echo the error, if not continue.
    if ($_FILES[$inputname]["error"] > 0){
        echo "Error: " . $_FILES[$inputname]["error"] . "<br />";
    }else{
      // Echo out File information.
 /* echo "Upload: " . $_FILES[$inputname]["name"] . "<br />";
  echo "Type: " . $_FILES[$inputname]["type"] . "<br />";
  echo "Size: " . ($_FILES[$inputname]["size"] / 1024) . " Kb<br />";
  echo "Stored in: " . $_FILES[$inputname]["tmp_name"]; */
    }

    // Get the extension so we can rename using the previous function.
    $ext = findexts($_FILES[$inputname]["name"]);

    $newpicturename = $storenum . $picturenum . "." . $ext;
    // Check to see if the file exists, if it does then tell the user. If not continue.
    if (file_exists("userimages/" . $newpicturename)){

      echo "<br>" . $newpicturename . " already exists. ";

      }else{

    // Uploads the file.
      move_uploaded_file($_FILES[$inputname]["tmp_name"], "userimages/" . $newpicturename);

    $picturefield = "picture" . $picturenum;
    $picturepath = "userimages/" . $newpicturename;
    //Inserts data into ad DB
    mysql_query("UPDATE storead SET $picturefield='$picturepath' WHERE storenum='$storenum'");
    // Tells the User.
     // echo "Stored in: " . "userimages/" . $newpicturename;
      }

  }else{
      // If the upload does not meet the parameters above, then tell the user and cancel.
      echo "Error uploading " . $_FILES[$inputname]["name"] . ". File may be too large or of unnacepted format.";
  }

}

Спасибо :)


person Chris Bier    schedule 19.08.2009    source источник


Ответы (3)


Вместо move_uploaded_file () вы должны загрузить файл в библиотеку обработки изображений, изменить его размер и сохранить.

например. используя GD, начните с imagecreatefromgif (), imagecreatefromjpeg () или imagecreatefrompng () (в зависимости от того, какой формат у вас есть), затем создайте новое изображение желаемого размера эскиза с помощью imagecreatetruecolor () и измените размер исходного изображения в нем с помощью imagecopyresampled (). Наконец, сохраните результаты с помощью imagegif () / imagejpeg () / imagepng () в зависимости от того, какой формат вы хотите.

Определить целевой размер довольно просто, если вам просто нужна фиксированная ширина при сохранении соотношения сторон: new_height = round_to_whole_pixels (new_width * original_height / original_width). Однако стоит провести некоторые проверки: скажем, кто-то загружает изображение размером 1x2000 пикселей. Стремясь к ширине (скажем) 200 пикселей, вы затем увеличили бы его до 200x400000, огромного изображения, которое могло бы съесть всю память вашего сервера! Так что имейте также max_height.

Наконец, ваш сценарий в его нынешнем виде содержит слишком много серьезных дыр в безопасности, чтобы их перечислить. Прежде чем размещать что-либо подобное в общедоступном Интернете, вам необходимо узнать об атаках обхода каталогов, SQL-инъекциях, HTML-инъекциях (XSS) и уязвимостях сниффинга типа загрузки файлов (например, встраивание JavaScript в HTML, замаскированный под файл изображения).

ETA:

Как вы думаете, этот веб-сайт охватывает большинство баз?

Не совсем, но это начало. Этот совет:

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

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

  • некоторые браузеры отправляют имена файлов, некоторые целые пути, и вы не знаете формат путей к файлам на клиентском компьютере (разделители каталогов на различных платформах включают '/', '\', ':', '.' и, возможно, другие) .

  • что произойдет, если указанные имена файлов содержат запрещенные символы? Управляющие персонажи? Символы Юникода?

  • если вы работаете на сервере Windows, попробуйте создать файлы с безобидными на вид, но зарезервированными именами, такими как «com», и у вас получится обрезка. Кроме того, Windows незаметно удаляет конечные пробелы и точки, что может легко запутать ваши сценарии.

Последнее является потенциальной дырой в безопасности связанного вами сценария. Он проверяет наличие «плохих» расширений файлов, таких как «.php», в конце имени файла. Но если вы загрузите файл с именем «x.php» (с пробелом) на сервер Windows, он с радостью примет его и сохранит как «x.php». (В скрипте также есть ошибка, поскольку он использует «.» В регулярном выражении, которое обозначает любой символ. Таким образом, имя файла «poo.potatophp» будет рассматриваться как имеющее расширение .php.)

Как обычно, белый список лучше, чем черный. Разрешение только напр. Расширения .jpeg с большей вероятностью сработают, чем отказ от заведомо плохих. Однако этого все же недостаточно, поскольку нет гарантии, что отправленный файл JPEG действительно будет иметь расширение «.jpeg». В Windows он может иметь расширение «.jpg» или «.pjpeg» или что-то еще, что оказывается сопоставленным с JPEG на клиентском компьютере. На Mac или Linux у него может вообще не быть расширения имени файла!

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

На странице также не рассматривается случай «HTML, замаскированный под файл изображения», о котором я упоминал. Если вы разрешаете кому-либо загружать файлы, которым вы не полностью доверяете, с полным доступом ко всему на вашем сайте, вам нужно об этом побеспокоиться. Вы можете прочитать об этом здесь. Дополнительное обсуждение рисков сценария загрузки файлов PHP см. здесь.

ETA2:

Я видел много предложений по загрузке над веб-каталогом. Тем не менее, мой сценарий по-прежнему будет показывать эти файлы посетителям веб-сайта.

Да, это хорошее место для начала. Взяв контроль над процессом обслуживания в свои руки, вы избежите любых проблем с веб-сервером, обрабатывающим типы файлов неожиданными способами, вы можете использовать свои собственные известные безопасные имена файлов и добавив в свой сценарий заголовок Content-Disposition: attachment, в основном вы можете запретить браузерам обрабатывать активный контент, такой как JavaScript, как исходящий из контекста безопасности вашего сайта, вызывая проблемы межсайтового скриптинга.

Недостатком этого метода является то, что обслуживание файла через PHP происходит намного, намного медленнее, чем позволить это сделать веб-серверу. Вы можете улучшить ситуацию, реализовав загрузку заголовков HTTP-кеширования в вашем сценарии обслуживания файлов, но это большая работа, и она все равно будет не так быстро, как типичный веб-сервер, написанный на C и, возможно, с использованием сети на уровне ядра. хаки эффективности. Для файла, который вы обслуживаете время от времени, это не проблема. Для популярного изображения, постоянно просматриваемого на загруженном сайте, это совершенно бесполезно.

Кроме того, раньше возникали некоторые проблемы, когда Flash игнорировал заголовок Content-Disposition, что по-прежнему могло вызывать скрытые файлы для XSS через этот плагин. Сейчас они исправлены, но кто знает, какие еще плагины и странное поведение браузера могут быть там. Поэтому в целях безопасности лучше всего обслуживать загруженные вами ненадежные файлы с другого имени хоста, например. субдомен, например data.example.com. Это предотвращает утечку файлов cookie и данных аутентификации в двух контекстах безопасности. Если вы выберете способ вывода файлов на основе веб-сервера, вам определенно необходимо принять эту меру предосторожности.

Я просто хочу сделать это, это слишком сложно

Да, это выглядит обманчиво простой задачей, но на самом деле это не так. Некоторые очень известные веб-сайты столкнулись с проблемами безопасности из-за ненадежных загрузок; если веб-специалисты из Microsoft и Google не всегда могут понять это правильно, это, вероятно, довольно сложно ...

Не помогает то, что (как обычно для PHP) 99% руководств, посвященных подобным вещам, - полнейшая чушь.

person bobince    schedule 19.08.2009
comment
Спасибо, Боб, есть ли у вас хорошие ресурсы по безопасной загрузке изображений? - person Chris Bier; 20.08.2009
comment
Как вы думаете, этот веб-сайт охватывает большинство баз? mysql-apache-php.com/fileupload-security.htm - person Chris Bier; 20.08.2009
comment
Эндрю, я ищу простой способ сделать это, и я видел много предложений по загрузке поверх веб-каталога. Тем не менее, мой сценарий по-прежнему будет показывать эти файлы посетителям веб-сайта. Считаете ли вы, что это безопасный путь в сочетании с безошибочным внесением в белый список? и возможен ли такой белый список? Я просто хочу сделать это, это слишком сложно, лол. Спасибо!! - person Chris Bier; 21.08.2009
comment
Крис Б .: Самое важное на вашей стороне - убедиться, что файл, с которым вы собираетесь работать, является загруженным файлом и вы проверили типы mime. Но, честно говоря, все, что вам действительно нужно, - это наблюдать за функциями gd при открытии изображения. Если GD давит на изображение, значит, это недопустимый образ, поэтому удалите его. - person dcousineau; 21.08.2009
comment
Эндрю, спасибо за ваш вклад, мы очень ценим его. И да, в Интернете есть много дерьмовых руководств по этому поводу. Есть еще одна проблема - загрузка и изменение размера изображения. Я хочу принять ваш ответ, потому что он очень помогает, но в то же время мне все еще нужно решить эту проблему. - person Chris Bier; 24.08.2009

list($originalWidth, $originalHeight) = getimagesize($originalFile);
$width = 250; // whatever your fixed width is
$height = ceil(($width / $originalWidth) * $originalHeight);

Затем следуйте инструкциям Боба

person searlea    schedule 19.08.2009

// Get the image data.
// This REALLY needs some form of security, doing it like in this example is *bad*.
// There are other functions than "imagecreatefromjpeg" to handle other formats.
$image = imagecreatefromjpeg($_FILES["userfile"]["tmp_name"]);

// Get image dimensions.
$imgX = imagesx($image);
$imgY = imagesy($image);

// Get aspect ratio.
// Biggest dimension is what we will use to constrain the thumbnail.
if($imgX > $imgY) {
    $multiplier = 150 / $imgX;
} else {
    $multiplier = 150 / $imgY;
}

// Create a scaled down version of the uploaded image.
$thumb = imagecreatetruecolor($imgX * $multiplier, $imgY * $multiplier);
imagecopyresampled($thumb, $image, 0,0,0,0, $imgX * $multiplier, $imgY * $multiplier, $imgX, $imgY);

Комментарии в изобилии! Это примерно тот код, который я использую для создания эскизов в моей собственной галерее. Единственная проблема, которую я вижу, это то, что вам нужно, чтобы эскизы были чем-то другим, кроме квадратов в их максимальных размерах, поскольку этот код ограничивается только квадратом.

person grimman    schedule 20.08.2009
comment
Что мне делать с imagecopyresampled? Вот где я заблудился. это снова в темпе? Должен ли я просто продолжить загрузку файла как обычно? Спасибо! - person Chris Bier; 24.08.2009
comment
php.net/imagecopyresampled Обычно мы помещаем измененное содержимое $ image в $ thumb. - person grimman; 24.08.2009