Как говорил Линус Торвалдс (Linus Torvalds) - "Болтовня ничего не стоит. Покажите мне код.", а потому перейду сразу к скрипту. Скрипт для загрузки аватара.
if(empty($_FILES['filename']) && $_FILES['filename']['size'] > 30*1024) { print( '<span style="color:red;">Объем файла превышает 30 килобайт или файл не удалось принять!</span><br>'); } elseif (is_uploaded_file($_FILES['filename']['tmp_name'])) { $imginfo = getimagesize(realpath($_FILES['filename']['tmp_name'])); if ($imginfo[2] == '1' || $imginfo[2] == '2' || $imginfo[2] == '3') { if ($imginfo[0] == '100' && $imginfo[1] == '100') { if ($imginfo[2] == '1') { $im = imageCreateFromGif(realpath($_FILES['filename']['tmp_name'])); $w = imageSX($im); $h = imageSY($im); $w_new=40; $h_new=40; $im_mini = imageCreate($w_new, $h_new); imageCopyResized($im_mini, $im, 0, 0, 0, 0, $w_new, $h_new, $w, $h); if ($im && $im_mini) { imageJpeg($im, $_SERVER['DOCUMENT_ROOT'].'/ava/'.$_SESSION['uid'].'.jpg', 90); imageJpeg($im_mini, $_SERVER['DOCUMENT_ROOT'].'/avatars/mini_'.$_SESSION['uid'].'.jpg', 90); imageDestroy($im); imageDestroy($im_mini); $sql = mysql_query("UPDATE usr SET ava='".$_SESSION['uid'].".jpg' WHERE id='".$_SESSION['uid']."'"); if ($sql) { print( '<span style="color:green;">Аватар успешно загружен!</span><br>'); } } else print( '<span style="color:red;">Загруженный вами файл не является изображением!</span><br>');
} elseif ($imginfo[2] == '3') { $im = imageCreateFromPng(realpath($_FILES['filename']['tmp_name'])); $w = imageSX($im); $h = imageSY($im); $w_new=40; $h_new=40; $im_mini = imageCreate($w_new, $h_new); imageCopyResized($im_mini, $im, 0, 0, 0, 0, $w_new, $h_new, $w, $h); if ($im && $im_mini) { imageJpeg($im, $_SERVER['DOCUMENT_ROOT'].'/ava/'.$_SESSION['uid'].'.jpg', 90); imageJpeg($im_mini, $_SERVER['DOCUMENT_ROOT'].'/ava/mini_'.$_SESSION['uid'].'.jpg', 90); imageDestroy($im); imageDestroy($im_mini); $sql = mysql_query("UPDATE users SET avatar='".$_SESSION['uid'].".jpg' WHERE id='".$_SESSION['uid']."'"); if ($sql) { print('<span style="color:green;">Аватар успешно загружен!</span><br>'); } } else print('<span style="color:red;">Загруженный вами файл не является изображением!</span><br>'); } } else print('<span style="color:red;">Изображение должно иметь размеры 100x100!</span><br>'); } else print('<span style="color:red;">Не верный тип файла!<br>Поддерживаемые типы: jpg, png</span><br>'); } else print('<span style="color:red;">Возникла ошибка при загрузке изображения! Попробуйте снова.</span><br>'); Форма загрузки.
<form enctype="multipart/form-data" method="post" action="load.php"> <table> <tr><td>Изображение</td><td><input name="filename" type="file" /></td></tr> <tr align="center"><td colspan="2"><input type="submit" name="send" value="Загрузить" /></td></td></tr> </table> </form> Через multipart-форму во временный каталог на сервере загружается файл и далее обрабатывается приведенным выше кодом.
Идея проста. Проверяется, приходило ли что-нибудь через форму и объем того, что пришло, и для перестраховки делается проверка временного файла функцией is_uploaded_file(). Если все нормально, получаем информацию о загруженном файле (предполагая, что это изображение!) с помощью функции getimagesize(). Эта функция выдает тип изображения и его размеры в пикселях (а большего и не надо, если кто вспомнил полный набор возвращаемых значений!). В первую очередь проверяется тип изображения. За это отвечает 2-й (по индексу) элемент возвращаемого функцией массива. В данном примере используются форматы GIF,JPEG и PNG. То есть 2-й элемент результата должен равняться соответственно 1, 2 или 3. Данная проверка не только ограничит выполнение действий над изображением неподходящего формата, но и не пропустит любой другой файл кроме изображения (например файл с php-скриптом!).
Далее, если изображение нужного формата, проверяется его размер в пикселях. За это отвечают 0-й и 1-й (высота и ширина) элементы результата функции. И если размер соответствует требуемому, производится "считывание" изображения из временного файла с помощью функции imageCreateFromGif, imageCreateFromJpeg или imageCreateFromPng (в зависимости от считанного ранее формата) и создание его миниатюры с помощью функции imageCopyResized(). Затем полученные изображения сохраняются в нужный каталог на сервере с помощью функции imageJpeg, imageGif или imagePng (в зависимости от нужного формата). Но в данном примере изображения в любом случае сохраняются в формате JPEG. Это делается из соображений экономии места на сервере. Как показала практика, изображение, которое в PNG формате весит 16 КБ, с мизерными (незаметными!) потерями в качестве в JPEG формате может весить 3 КБ. Я думаю, тут замечания по поводу мелочности будут неуместными (зачем хранить лишний объем?). Ну это уже кому как нравится.
В общем целом вся идея загрузки с точки зрения безопасности хороша тем, что оригинальный файл, полученный через форму с компьтера пользователя, не уходит дальше временного каталога и удаляется автоматически после завершения работы скрипта. То есть, даже если это будет изображение, в которое в метаданных зашит какой-либо скрипт, будет загружено на сервер "чистым". И, кроме того, при использовании формата JPEG для сохранения, изображение может быть неплохо ужато, а скрипт загрузки может быть укорочен, путем оформления всех манипуляций с изображением в функцию.
Безопасность, это не только загрузка на сервер, а также вывод этих аватаров ... Просто если загружать данным образом, то никакого труда не составит сливать абсолютно все аватары куда угодно! А это ни есть copyright-но
Ну, во-первых, я ставил задачу - загружать "чистые" картинки. А во-вторых, поясни на счет "сливать куда угодно". Путь для сохранения аватаров постоянный... А на счет copyright-но... Если пользователь загружает на сайт какое-то фото (и если его могут видеть все!), то он должен понимать, что он этим действием разрешил распространение этой фотографии. К стати на Facebook'е при загрузке фотографий сразу так и предупреждают.
Сливать куда угодно я и имел ввиду то, что данным кодом ты создал пополняемую базу аватаров! Т.е. трафик твоего сайта будет уходить на сторонние ресурсы без какой либо трудности!
Есть идеи по ограничению утечки трафика? Конечно, если выводить аватары напрямую, само собой ссылки на них смогут использовать где угодно. Но с другой стороны, если принимать всякие меры по ограничению их распространения (вот на счет этого ТВОИ ИДЕИ!), это тоже будет хавать трафик... Ну а вообще это уже тема для другой статьи...
А... так вот что ты имел в виду! Типа в скрипте все имена аватаров по id пользователя выдаются... Да точно... Я даже как-то сразу и не заметил подвоха.
Добавлять комментарии могут только зарегистрированные пользователи. [ Регистрация | Вход ]