2010-07-18 3 views
2

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

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

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

$extension = substr($filename, strpos($filename,'.'), strlen($filename)-1); 
$filetypes = array('.jpg', '.jpeg', '.gif', '.bmp', '.png', '.JPG', '.PNG', '.JPEG', '.GIF', '.BMP'); 
if($_FILES['image']['error'] == 4){ 
    $error = "No image"; 
    return $error; 
} 
else if(($_FILES['image']['error'] == 2) || ($_FILES['image']['error'] == 1)){ 
    $error = "File size too big"; 
    return $error; 
} 
else if(!in_array($extension, $filetypes)){ 
    $error = "This isn't an image that is supported"; 
    return $error; 
} 
else if(($_FILES['image']['error'] == 7) || ($_FILES['image']['error'] == 3)){ 
    $error = "Error occurred. Try again"; 
    return $error; 
} 
else{ 
    if(($extension == '.jpg') || ($extension == '.jpeg')){ 
    $source = imagecreatefromjpeg($uploaded); 
    } 
    else if($extension == '.png'){ 
    $source = imagecreatefrompng($uploaded); 
    } 
    else{ 
    $source = imagecreatefromgif($uploaded); 
    } 
    list($width, $height) = getimagesize($uploaded); 
    $ratio = $width/$height; 
    $new_width = 300; 
    $new_height = round(300/$ratio); 
    $canvas = imagecreatetruecolor($new_width, $new_height); 
    imagecopyresampled($canvas, $source, 0, 0, 0, 0, $new_width, $new_height, $width,  $height); 
    $name = date("dmyHis").rand(0, 9); 
    $path = $_SERVER[ 'DOCUMENT_ROOT' ] . '/images/uploaded/'.$name.'.jpg'; 
    $new_image = imagejpeg($canvas, $path, 100); 
    $poster['name'] = $name.'.jpg'; 
    $poster['width'] = $new_width; 
    $poster['height'] = $new_height; 
    return $name.'.jpg'; 
} 

Как он стоит, есть несколько ошибок, которые я знаю об этом, или не полностью смотрели в, например, некоторые изображения метательных ошибку из imagecreatefromwhatever, и если имя изображения есть «» в нем он также выдает ошибку.

Как только процесс будет завершен, я сохраню имя изображения в поле «плакат» в MySQL, которое будет использоваться для получения правильного изображения из папки при просмотре.

Что я действительно хотел знать, есть ли какие-либо другие проблемы, с которыми я, вероятно, столкнулся с загрузкой изображений?

  • Я ожидаю достаточного количества трафика, так будет ли этот код работать с большим использованием?
  • Есть ли другие подводные камни или вещи, которые я должен искать?
  • Я использую лучший метод для работы?
  • Ограничение размера файла на данный момент составляет 2 МБ, это слишком высокое?
  • Даже если пользователь загружает что-то более 2 МБ, сценарий все равно будет работать, и я предполагаю, что файл будет загружен на сервер для удаления имен и сравнения файлов и т. Д., Как это повлияет на использование моей полосы пропускания?
  • Как долго постоянные файлы остаются на сервере?

Если у кого-то есть хорошие чтения по этому вопросу, я был бы очень признателен!

спасибо.

Редактировать: Форматирование.

Редактировать 2: Я не уточнил исходные файлы. Я имею в виду исходные файлы, к которым я использую переменную $ _FILES для доступа. Скажем, что это 1,9 МБ, будет ли изображение на 1,9 МБ на сервере все время, когда я буду заниматься расширением и тем? Должен ли я очистить это, как только я создал новое изображение?

ответ

3

Расширения как отправленный пользователем в имени файла нельзя доверять или полагаться. Некоторые пользователи считают, что изменение «jpg» на «gif» делает его gif и т. Д.

Я предлагаю использовать getimagesize FIRST для проверки правильности изображения и получения типа exif. Не беспокойтесь об извлечении расширения, поскольку он бесполезен. Тип exif будет в 2 массива, возвращаемого getimagesize.

Кроме того, изображения CYMK являются проблемой. Некоторым людям удается загружать jpegs CYMK. Проверка каналов будет определять эти изображения. Это должно быть 3, RGB.

$image_info=getimagesize($your_image_file); 
if($image_info['channels']==4) 
    { 
    //it's invalid - cymk 
    //browsers cannot display these images. It might be possible to convert them to RGB explicitly... 
    } 

$real_exif=$image_info[2]; 
if($real_exif>0 && $real_exif<4){ 
//it is a png, gif or jpg 
} 

Тип возвращается EXIF ​​в качестве константы, как IMAGETYPE_GIF, где численно, 1 представляет собой GIF, JPG 2, и 3 PNG. Вы можете использовать image_type_to_extension для преобразования в расширение текстового файла.

Теперь, иногда я обнаружил, что getimagesize не смог найти exif-тип для изображений, которые были действительными, и с ним можно было бы работать с imagemagick/GD. Он не смог вернуть EXIF ​​для них, поэтому их неправильно отклонили. Я придумал этот мерзкий хак, чтобы хотя бы обнаружить тип и дать им попробовать ...

[email protected]($temp_name,'r'); 
    if($handle) 
    { 
    $chars=fread($handle,24); 
    if(stripos($chars,'jfif')!==false) 
     {$type=2;} // found a jpg 
    elseif(stripos($chars,'png')!==false) 
     {$type=3;} // found a png 
    elseif(stripos($chars,'gif')!==false) 
     {$type=1;} // found a gif 
    else 
     { 
     //file type could not be determined 
     } 
    } 
+0

Я не считал, что имя файла может быть плохим. Спасибо за подсказку по getimagesize. Что касается каналов изображения, я понятия не имел, что CYMK вызовет проблемы. Очень полезная информация, спасибо! – chudley

+1

Хорошая точка в файле. Смешная причуда php заключается в том, что вы можете сказать 'imagecreatefromstring()', и тогда вам не нужно знать тип - довольно странный, но истинный. Таким образом, вы можете загрузить изображение, используя '$ imagedata = file_get_contents ($ filename);'. (обратите внимание, что в средах с общим хостингом, где память может быть ограничена, это будет дополнительно 2 Мб) – mvds

4

Прежде всего, молодец, похоже, что вы много работаете в нем.

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

Вы принимаете все с первого . как расширение, так как оно стоит сейчас. Поэтому ошибка, когда кто-то помещает . в имя файла. Это можно сделать лучше.

$extension = ''; 
if (preg_match("/\\.([a-z]+)$/i",$filename,$match)) 
{ 
    $extension = strtolower($match[1]); 
} 

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

Считывание изображения с if JPG else if PNG else GIF не очень чистое: вы должен также проверить gif и только , затем перейдите в категорию «else» и просто выбросите ошибку. (что означает, что вы можете сбросить чек, который вы делали раньше!)

Когда вы говорите $source = imagecreatefrom...($filename), вы лучше добавьте его с помощью @, чтобы избежать предупреждения об поврежденных изображениях (обычно, не используйте @, но в этом случае вы не можете знать если изображение повреждено). Затем обязательно проверьте возвращаемые значения (ВСЕГДА делать), как

$source = @imagecreatefrompng($filename); 
if (!$source) return "Error parsing image"; 

Теперь изображение загружено, поэтому размер, если это известно; вам не нужно снова запрашивать файл. Вместо getimagesize() вы можете использовать imagesx($source) и imagesy($source)

Этого достаточно, чтобы исправить на данный момент, я думаю. ;-)

Редактировать: Tiny problem btw with rand (0,9) в имени файла, что означает, что шансы большие, вы получаете файлы, смешанные, если более одной загрузки клиента в течение одной секунды. (с 11 загрузками в секунду у вас есть проблема точно)

+0

Спасибо за ответ! Ошибка полной остановки - это то, о чем я знаю, но еще не разобрался, но взглянем на код, который вы предложили, спасибо! Что касается if if JPG else и т. Д., Это звучит как лучший способ справиться с операторами if, я реализую это как можно скорее. Исправление $ source и @ sign отлично смотрится также. Я действительно не рассматривал поврежденные изображения. Спасибо за совет! Теперь, когда вы упомянули об этом, более одной загрузки в ту же секунду не так уж далеки, как мысль! Я изменю это! Благодарим за отзыв! – chudley

4

Богатый, я сделал схожую, в первую очередь с iMagick. GD функционально подобен, поэтому я не жду никаких проблем. Мой сайт обрабатывал сотни изображений в неделю без проблем и надежно служил ~ 1k/week. Я делал всю обработку на бэкэнд, как кажется, вы делаете в этом примере, поэтому мало беспокоится о тяжелом входящем трафике (например, о пикапе на DIGG), дробящем ваш сервер.

Самая большая проблема в том, что вы открываете к уязвимости, разрешая загрузку любого типа. Вы, наверное, слышали, что ребята из службы безопасности говорят, что единственный способ защитить от хакеров - это выйти из Интернета ... это так. Я не был бы в полном страхе, потому что похоже, что вы предприняли справедливые шаги для проверки типов и размеров файлов. Дополнительным соображением является просмотр разрешений на вашем сервере - откройте каталог, который будет писать только пользовательскому агенту сервера, и заблокируйте просмотр в каталоге для дополнительной безопасности. Если вы хотите быть вдвойне безопаснее, напишите в другую учетную запись (если у вас есть такая возможность), чтобы ограничить доступ к вашему коду. Это не обязательно, но это хороший дополнительный шаг, если у вас есть проблемы. Наконец, разместите ваш загрузчик за простой системой паролей с помощью captcha, чтобы заблокировать проверки с помощью автоматического использования ... предоставить пользователям бесплатный доступ с простым шагом регистрации. Это небольшая проблема с пользовательским интерфейсом, но может иметь разницу в безопасности.

Возможно, я остановлюсь на процессе, если файл пользователя превышает 2 МБ. Это всего лишь я. Вы не захотите, чтобы система рухнула и сгорела, если какой-либо пользователь попытается создать файл с расширением .jpg на вашем сервере. Пропускная способность, скорее всего, будет проблемой только в том случае, если вы размещаете себя самостоятельно или если вы платите за это, это повысит вашу пропускную способность, но даже при сто загрузках в день вы, вероятно, не собираетесь стандартный сервер за его пределами, если соответствующий трафик, посещающий сайт, не достигнет тысячи. Большинство хостов позволит вам контролировать нагрузку на сервер. Мне очень повезло с дешевой личностью с HostGator

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

+0

Да, любое взаимодействие с пользователем не заслуживает доверия. У меня простой процесс регистрации пользователей, поэтому, надеюсь, это напугает случайный спам. Хорошая идея с доступом пользователя к папке. Я сделаю некоторые исследования в этом. Приятно слышать о пропускной способности, с которой вы имеете дело. Сейчас я могу вздохнуть с облегчением! Но в отношении файлов на сервере я имел в виду исходные файлы, которые пользователь загрузит. Итак, изображение, которое имеет переменная $ _FILES, если это имеет смысл? Я обновлю оригинальное сообщение, чтобы попытаться объяснить немного лучше. Спасибо за ответ! – chudley

+0

Я не уверен, что вы можете определить, прошел ли файл над лимитом 2 МБ во время загрузки - когда он смотрел на него в прошлом, он казался очень сложным. – JAL

+0

Алекс, конечно. По умолчанию загрузка PHP идет во временную папку. Вы проверяете перед выполнением файла move_uploaded_file. Как упоминает Rich, он проверяет размер файла перед тем, как перейти к указанному выше коду. – bpeterson76

3

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

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

я использовал функцию CHMOD для изменения прав доступа после загрузки и то он работал надежно.

Вот статья об этом (не моей статье, но это было полезно): http://drupal.org/node/34028

Смежные вопросы