Что учитывать при загрузке файлов на сервер
Если Вы программируете на php, то, наверняка, хотя бы раз в жизни Вам приходилось сталкиваться с организацией загрузки файлов на сервер.
Например, создавать простенький блог, в котором автор может прикреплять к своим статьям изображения. А может быть, огромную социальную сеть, где пользователи будут добавлять аватарки к своим профилям. Или же простейшую галерею фотографий. Объединяет все эти примеры одно – в них будет происходить загрузка пользовательского файла на сервер.
Для того чтобы напомнить Вам, как файл загружается на сервер, рассмотрим простенький скрипт. Нам потребуется html –формочка и её php-обработчик.
Итак, форма:
<form method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="Загрузить файл!">
</form>
В ней нет никаких примечательных моментов за исключением указания enctype = «multipart/form-data», которое необходимо, если с формы мы осуществляем загрузку файла.
Теперь напишем самый простой php-обработчик:
<?php
if (isset($_FILES['file'])) // если была произведена отправка формы
{
// копируем файл из временной директории
copy($_FILES['file']['tmp_name'], $_FILES['file']['name']);
echo 'Файл успешно загружен';
}
Объединим это всё в один файл:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Загрузка файла на сервер</title>
</head>
<body>
<form method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="Загрузить файл!">
</form>
<?php
if (isset($_FILES['file'])) // если была произведена отправка формы
{
// копируем файл из временной директории
copy($_FILES['file']['tmp_name'], $_FILES['file']['name']);
echo 'Файл успешно загружен';
}
?>
</body>
</html>
А теперь давайте попробуем поискать недостатки у данного скрипта.
Во-первых, пользователь может просто не выбрать файл на форме. В итоге функция copy() попытается скопировать из временной директории файл, которого нет, что приведёт к ошибке.
Во-вторых, пользователь может выбрать фотографию, которая весит, допустим, мегабайт 20 (а если он злоумышленник или шутник – видеофайл весом в 20 Гб). Стоит задуматься, нужны ли нам файлы такого размера у себя на сайте!?
Обработаем в скрипте обе эти ситуации (изменения показываются в обработчике):
<?php
// если была произведена отправка формы
if (isset($_FILES['file']))
{
//если имя файла пустое
if($_FILES['file']['name'] == '')
echo ('Файл не выбран!');
//если размер файла превышает 1 Мб
elseif($_FILES['file']['size'] > 1048576)
echo ('Размер файла превышает 1 Мб!');
else{
// копируем файл из временной директории
copy($_FILES['file']['tmp_name'], $_FILES['file']['name']);
echo 'Файл успешно загружен';
}
}
Ну что ж, кажется, всё! Осталось лишь где-нибудь добавить проверку на расширение загружаемого файла, и всё будет готово?
Нет! Сейчас нам необходимо вспомнить, из каких частей состоит закачка файла на сервер:
- файл с компьютера пользователя автоматически загружается на сервер в директорию, где хранятся все временные файлы. На денвере, например, это папка tmp;
- мы выполняем все проверки и перемещаем файл из временного хранилища в реальное с помощью функции copy().
Т.е. смотрите, что происходит: файл сразу же оказывается на сервере ещё до того, как исполнится первая строчка нашего php-кода. Где же тогда ставить защиту от загрузки злоумышленниками и шутниками файлов огромных размеров?
Может быть, с помощью скрытого поля на html-форме? Например:
<form method="post" enctype="multipart/form-data">
<input name="MAX_FILE_SIZE" value="1048576">
<input type="file" name="file">
<input type="submit" value="Загрузить файл!">
</form>
Как бы бредово не выглядела данная запись, но она реально работает. С помощью дополнительного скрытого поля ввода:
<input name="MAX_FILE_SIZE" value="1048576">
Как бы бредово не выглядела данная запись, но она реально работает. С помощью дополнительного скрытого поля ввода:мы на стороне клиента ставим ограничение на размер передаваемого файла. К сожалению, данная запись спасает только от обычных пользователей. Шутники или злоумышленники легко смогут подделать отправку формы.
Поэтому, единственным нормальным способом ограничивать размер файлов, загружаемых на сервер, являются настройки в конфигурационном файле php на сервере. Рассмотрим необходимые настройки на примере файла php.ini на денвере.
Находится он по адресу /usr/local/php5/php.ini. Советую Вам сейчас его открыть (если Вы конечно используете денвер).
Итак, здесь нас интересует 552-ая строчка:
upload_max_filesize = 2M
Как мы видим, по умолчанию в денвере файлы больше 2Мб загружаться не будут. В реальных проектах это может быть много, а может быть и мало. Советую данную настройку менять исходя из конкретных решаемых задач.
Всё, теперь мы можем грамотно управлять размером загружаемых на сервер файлов. Осталось только разобраться с их количеством. Согласитесь, что если пользователь подделает отправку формы и наплодит на ней 1000 полей ввода, в которые поместит по двухмегабайтному файлу, результат для нас также будет очень печальным.
Установить максимальное количество загружаемых на сервер файлов мы можем с помощью специальной функции ini_set(). В самое начало нашего скрипта допишем:
ini_set(‘max_file_uploads’, ’5′);
Ура! Теперь за один раз никто не сможет загрузить к нам на сервер более 5 файлов.
Подводя итоги, хочу ещё раз перечислить все пункты, про которые Вы должны помнить, если организуете загрузку файлов на сервер:
- у html формы обязательно указывайте enctype = «multipart/form-data»
- делайте проверку, не является ли имя файла пустым (т.е. выбрал ли вообще пользователь файл)
- делайте проверку на размер и тип загружаемого файла в скрипте
- устанавливайте максимальный размер загружаемого файла в конфигурационном файле на сервере
- с помощью функции ini_set() устанавливайте максимальное количество загружаемых файлов
21.03.2015
Понравился материал? Поделись с друзьями!