PHP изменение размера и мой скрипт загрузки - PullRequest
1 голос
/ 20 августа 2009

Я видел много примеров, но я не уверен, как это может быть связано со сценарием загрузки, который у меня есть на данный момент. Может кто-нибудь объяснить, как я мог бы использовать 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.";
  }

}

Спасибо:)

Ответы [ 3 ]

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

Вместо 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.)

Как обычно, белый список лучше, чем черный. Разрешить только напр. Расширения j .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% уроков, посвященных подобным вещам, - полная чушь.

1 голос
/ 20 августа 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);

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

1 голос
/ 20 августа 2009
list($originalWidth, $originalHeight) = getimagesize($originalFile);
$width = 250; // whatever your fixed width is
$height = ceil(($width / $originalWidth) * $originalHeight);

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

...