Как загрузить файлы на сервер

Как загрузить файлы на сервер
Как загрузить файлы на сервер

Оглавление:

Каждый из нас когда-то загружал какие-то файлы в интернете. Например, это могло быть изображения на форуме или фотографии в социальные сети.

Поэтому, перед программистами, которые создают такие порталы, всегда стоит вопрос, как загрузить файлы на сервер.

Вот эту задачу мы и разберем в данной статье.

Предполагается, что у Вас уже установлен локальный сервер и настроены виртуальные хосты.

Создание формы для загрузки файла (изображения)

Начнем с простого. Для начала разберёмся как загрузить на сервер один файл.

Например, мы хотим загрузить какое-то изображение в одном из форматов jpg или png.

Создаем файл index.php. Добавляем в него базовую структуру HTML

Базовая структура HTML страницы

    	<!DOCTYPE html>
		<html lang="ru">
		<head>
		    <meta charset="UTF-8">
		    <title>Как загрузить файл на сервер</title>
		</head>
		<body>


		</body>
		</html>
    

Теперь, создаем CSS файл styles.css и подключаем его к странице.

Как подключить css к html странице

Также подключим через CDN CSS фреймворк Bootstrap

    	<!DOCTYPE html>
		<html lang="ru">
		<head>
		    <meta charset="UTF-8">
		    <title>Как загрузить файл на сервер</title>
		    <link rel="stylesheet" type="text/css" href="styles.css" />
		</head>
		<body>


		<!-- Bootstrap CDN -->
		<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
		<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
		<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
		<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

		</body>
		</html>
    

Теперь, создаем HTML форму. Для красоты, оформляем страницу с помощью классов CSS фреймворка Bootstrap.

Поле для загрузки изображения будет иметь имя file_img. Данное имя будет использоваться в названии ячейки из суперглобального массива $_FILES, которая будет содержать массив с данными о загруженном файле.

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

Так как мы хотим, чтобы пользователь загружал только изображения в формате jpg или png, то необходимо сообщит пользователю об этом.

В тоже время, мы должны сообщить пользователю максимальный размер изображения, который доступен для загрузки.

Допустим, мы не хотим, чтобы пользователь смог загружать на сервер изображение, размер которого превышает 3 мегабайт.

Поэтому, мы должны вывести на страницу еще одно сообщение, которое предупреждает и о размере.

Сразу после тега <form>, добавляем соответствующие сообщения.

В итоге страница имеет такой код:

    	<!DOCTYPE html>
		<html lang="ru">
		<head>
		    <meta charset="UTF-8">
		    <title>Как загрузить файл на сервер</title>
		    <link rel="stylesheet" type="text/css" href="styles.css" />
		</head>
		<body>

		    <div class="container">

		        <div class="row mb-3">

		            <div class="col-md-12">
		                <form action="upload-one-file.php" method="POST" enctype="multipart/form-data" class="form-inline md-form">

		                    <p class="text-info">Разрешается к загрузки только изображения в формате jpg или png</p>
							<p class="text-info">Максимальный размер загружаемого файла, не должно превысить 3MB</p>


		                    <div class="input-group">
		                        <div class="custom-file">
		                            <input type="file" name="file_img" id="file_img" required>
		                        </div>
		                    </div>

		                    <button type="submit" name="upload_image" class="btn btn-primary">Загрузить изображение</button>
		                </form>
		            </div>
		        </div>
		    </div>

		    <!-- Bootstrap CDN -->
		    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
		    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
		    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
		    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

		</body>
		</html>
    

Для того чтобы разместить форму по центру страницы, в файле styles.css добавляем эти стили:

    	.container{
    	    padding-top: 200px;
    	}

    	form{
    	    width: 550px;
    	    margin: 0 auto;
    	}
	

Страница приобрела такой внешний вид:

форма для загрузки файла
Форма для загрузки изображения на сервер

Отправка формы на сервер

В значение атрибута action тега формы, мы указали что данные с формы будут обрабатываться в файле upload-one-file.php, поэтому создаем этот файл.

Для того чтобы нагляднее увидеть, что находится в массиве $_FILES, выведем его содержимое на экран.

	    <?php

	        // Код из файла upload-one-file.php 
	        echo '<pre?>';
	        print_r($_FILES);
	        echo '</pre?>';
	        
	    ?>
    

Как было упомянуто выше, в суперглобальном массиве $_FILES, добавляется массив с данными о загруженном файле, имя которого указано в значение атрибута name, поля загрузки файла.

Открываем страницу в браузере, выбираем какое-то изображение и нажимаем на кнопку ‘Загрузить изображение’.

В результате, мы видим содержимое суперглобального массива $_FILES.

Содержимое суперглобального массива $_FILES
Содержимое суперглобального массива $_FILES

Разберемся с каждой ячейкой из массива file_img, с данными о загруженном файле.

  • name – название загруженного файла
  • type MIME-type . То есть тип загруженного файла.
  • tmp_name - это временный путь где был загружен файл. То есть интерпретатор PHP, загруженному файлу задал некое временное имя (в нашем случае php34B6.tmp) и поместил его в временную папку (D:\OpenServer-5.3.7\userdata\php_upload\). Нам остается, специальной функцией переместить данный файл из временного хранилище в нужную папку на сервере.
  • error - код ошибки. Значение 0, означает что ошибок нет.
  • size - размер загруженного файла в байтах. В нашем случае, изображение cart.jpg имеет 164358 байтов.

Выводим сообщение после отправки формы

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

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

А если файл загружен на сервер успешно, то вывести пользователю сообщение о том что файл загружен успешно.

Возвращать пользователя обратно на страницу будем с помощью функции header (), а для того чтобы отправить сообщение с сервера в клиентскую часть, воспользуемся сессией.

И так, приступим. В начале файла обработчика upload-one-file.php, открываем сессию.

        <?php

            // Код из файла upload-one-file.php
            session_start();

        ?>
    

Теперь, для того чтобы знать куда перенаправить пользователя, необходимо узнать адрес сайта с протоколом. После запуска сессий пишем:


        // Код из файла upload-one-file.php

        $protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
		$address_site = $protocol.$_SERVER['SERVER_NAME']; // Адрес сайта
        
    

Для проверки, симулируем ошибку с сервера. Добавим некое сообщение об ошибке в сессию и перенаправляем пользователя обратно на страницу загрузки изображения.


        // Код из файла upload-one-file.php 

        if(true){

            // Добавляем в сессию сообщение об ошибке.
            $_SESSION["server_messages"] = "<p class='text-danger font-weight-bold'> Ошибка с сервера </p>";

            // Возвращаем пользователя обратно на страницу загрузки изображения
            header("Location: ".$address_site);

            // Останавливаем скрипт
           exit();
        }
        
    

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

Так как сообщения будут находиться в сессии, то для того чтобы получить к ним доступ необходимо запустить сессию и в файле index.php.

В самом начале файла index.php, пишем:

	    <?php

            // Код из файла index.php 
	        session_start();

	    ?>
    

Теперь, после формы добавляем такую проверку, если в массиве $_SESSION, существует ячейка server_messages, то выводим ее содержимое.

Создадим блок div с классом .server_messages, куда и будем выводить сообщения с сервера.

	    <?php
	        if(isset($_SESSION["server_messages"])){
	    ?>
	    		<div class="server_messages">
	    			<?php echo $_SESSION["server_messages"] ?>
                </div>
        <?php
            	//Уничтожаем ячейку с сообщением, чтобы не появилось заново при обновлении страницы
                unset($_SESSION["server_messages"]);
            }
        ?>
    

Добавим некие стили для данного блока в файле styles.css:

    	.server_messages, form{
    	    width: 550px;
    	    margin: 0 auto;
    	}

    	.server_messages{
    	    margin-top: 10px;
    	}
    

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

сообщение после отправки формы
Вывод сообщения после отправки формы

Переходим обратно в файл upload-one-file.php, и удаляем тестовую проверку.

То есть удаляем этот код:

	    <?php
	        if(true){

	            // Добавляем в сессию сообщение об ошибке.
	            $_SESSION["server_messages"] = "<p class='text-danger font-weight-bold'> Ошибка с сервера </p>";

	            // Возвращаем пользователя обратно на страницу загрузки изображения
	            header("Location: ".$address_site);

	            // Останавливаем скрипт
	           exit();
	        }
	    ?>
    

Теперь, необходимо добавить проверку, была ли нажата кнопка "Загрузить изображение".

Дело в том, что сейчас злоумышленник может ввести в адресную строку браузера название файла обработчика ( например: http://site.test/upload-one-file.php ) и открыть его напрямую.

	    <?php
	        session_start();

	        $protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
	        $address_site = $protocol.$_SERVER['SERVER_NAME']; // Адрес сайта

	        /*
	            Проверяем была ли отправлена форма, то есть была ли нажата кнопка “Загрузить изображение”. Если да, то идём дальше, если нет, то выведем пользователю сообщение об ошибке.
	        */
	        if(!isset($_POST["upload_image"])){

	            exit("<p><strong>Ошибка!</strong> Вы зашли в обработчик формы напрямую, поэтому нет данных для обработки.</p><p> Вы можете перейти на <a href=".$address_site."> главную страницу сайта </a> </p>");
	        }

	        // (1) Место для следующего куска кода
    

Проверяем тип ( MIME-type ) загруженного файла

Теперь, поговорим немного о параметре type из массива с данными о файле file_img из суперглобального массива $_FILES.

Как мы знаем, существуют много типов файлов с разными расширениями.

  • Аудио файлы с расширением .mp3 имеют MIME-тип audio/mpeg
  • Видео файлы с расширением .avi, имеют MIME-тип video/avi
  • Документы с расширением .pdf, имеют MIME-тип application/pdf
  • Изображения с расширением .png, имеют MIME-тип image/png
  • И другие

Также, существуют и опасные файлы, например, с расширением .bat, которые имеют MIME-тип application/octet-stream. В таких файлах злоумышленник может записать какой-то вредоносный скрипт или команду.

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

В целях безопасности, для того чтобы не разрешать загрузку других файлов кроме изображений, на стороне сервера мы должны проверить MIME-тип загруженного файла.

Для этого, создаем массив, в котором указываем какие MIME-типы разрешены для загрузки.

В нашем случае указываем что разрешены для загрузки файлы которые имеют MIME-тип "image/jpeg" либо "image/png"

Далее, проверяем, если MIME-тип загруженного файла не находится в массиве с разрешенными типами, то перенаправляем пользователя обратно на страницу загрузки изображения и выводим ему соответствующее сообщение об ошибке.

Теперь пишем проверку типа файла, после метки "// (1) Место для следующего куска кода":

		
		    // указываем какие MIME-типы разрешены для загрузки
		    $allow_types = ['image/jpeg', 'image/png'];

		    // проверяем MIME-тип загруженного файла и если данный тип не находятся в массиве с разрешенными типами,
		    // то, возвращаем пользователя обратно на страницу загрузки и выводим ему соответствующее сообщение об ошибке
		    if(!in_array($_FILES['file_img']['type'], $allow_types)){

		        // Сохраняем в сессию сообщение об ошибке.
		        $_SESSION["server_messages"] = "<p class='text-danger font-weight-bold'>Ошибка! Выбранный вами файл не является изображением </p>";

		        //Возвращаем пользователя обратно на страницу загрузки изображения
		        header("Location: ".$address_site);

		        //Останавливаем скрипт
		        exit();
		    }

		    // (2) метка: Место для следующего куска кода
		
	

Проверяем. Заходим в браузер и вместо изображения, загружаем файл другого типа. В результате получаем такую ошибку:

Файл не является изображением
Выбранный вами файл не является изображением

Проверяем расширение загруженного файла

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

То есть, он может написать скрипт, в котором укажет что хочет отправить .bat-файл и задать этому файлу MIME-тип 'image/jpeg' или 'image/png'.

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

		
		    // Массив с разрешенными расшерениями
		    $allow_extensions = ['jpg', 'jpeg', 'png'];

		    // Узнаем расширение загруженного файла
		    $extension_file =  pathinfo( $_FILES['file_img']['name'], PATHINFO_EXTENSION );

		    if(!in_array($extension_file, $allow_extensions)){
		        // Если расширение загруженного файла не находится в массиве с разрешенными расшерениями,
		        // то, останавливаем скрипт
		        exit();
		    }


		    // (3) метка: Место для следующего куска кода
		
	

Проверяем размер загруженного файла

И последнее что нам осталось проверить, это размер загруженного файла.

Мы указали что максимальный размер изображения, не должно превысить 3MB.

В массиве $_FILES мы имеем ячейку size, с размером загруженного файла в байтах.

И для того чтобы посчитать сколько байтов содержит 3 мегабайта, воспользуемся функцией return_bytes(),

Добавляем эту функцию в конце обработчика:

		
			function return_bytes($val) {
			    $val = trim($val);
			    $last = strtolower($val[strlen($val)-1]);
			    switch($last) {
			        // Модификатор 'G' доступен с PHP 5.1.0
			        case 'g':
			            $val *= 1024;
			        case 'm':
			            $val *= 1024;
			        case 'k':
			            $val *= 1024;
			    }

			    return $val;
			}

		
	

Передаем в функцию return_bytes значение '3M' и выводим на экран результат данной функции.

		<?php

			echo '3MB = '.return_bytes('3M').' байта';
			exit();

		?>
	

Мы видим, что 3MB = 3145728 байта.

Считаем это вручную.

1 мегабайт (MB) = 1048576 байт.

1048576 байт умножаем на 3 и узнаем, что 3MB это 3145728 байта.

В указанное место "// (3) метка: Место для следующего куска кода" пишем следующею проверку:

		

			if($_FILES['file_img']['size'] > return_bytes('3M')){
			    // Если размер загруженного изображения превышает 3MB то возвращаем ошибку

			    // Сохраняем в сессию сообщение об ошибке.
			    $_SESSION["server_messages"] = "<p class='text-danger font-weight-bold'>Ошибка! Размер загруженного изображения превышает 3MB</p>";

			    //Возвращаем пользователя обратно на страницу загрузки изображения
			    header("Location: ".$address_site);

			    //Останавливаем скрипт
			    exit();
			}

		
	

Пытаемся загрузить изображение с размером в 5MB и в результате получаем ошибку:

Размер загруженного изображения
Размер загруженного изображения превышает 3MB

Конфигурация интерпретатора PHP

Также мы должны учесть, что в конфигурации интерпретатора PHP (в файле php.ini) существуют 4 опции, которые влияют на загрузку файла.

upload_max_filesize - Устанавливает максимальный допустимый размер для загруженного файла.

post_max_size - Устанавливает максимально допустимый размер данных, отправляемых методом POST. В случае если необходимо загрузить большой файл, то значение этой опции должно быть больше значении, которое указано в опции upload_max_filesize.

max_execution_time – Устанавливает максимальное время в секундах, в которой может выполниться скрипт. По умолчанию это 30-60 секунд.

max_input_time – Устанавливает время в секундах, в течении которой будут обрабатываться приходящие данные на сервер. По умолчанию установлено значение '-1'. Это означает что в качестве значения для этого параметра будет использоваться значение max_execution_time.

Для того чтобы увидеть текущие значения этих опции, можно открыть страницу с результатом функции phpinfo();.

Сейчас у меня установлено что upload_max_filesize = 10M и post_max_size равен 20M.

Как определить, что значение post_max_size было превышено?

Теперь, если мы по пытаемся загрузить данные методом POST, размер которых превышает значение 20MB (это значение указано в настройках сервера, в параметре post_max_size ), то, согласно документации, в таком случае в суперглобальных массивах $_POST и $_FILES не записываются данные.

В результате мы увидим ошибку о том, что, нет данных для обработки.

Для того чтобы убедиться в этом, временно, выведем на экран содержимое суперглобальных массивов $_POST и $_FILES внутри первой проверки.


				if(!isset($_POST["upload_image"])){

    				echo 'Содержимое массива $_POST: <pre>';
    				print_r($_POST);
    				echo '</pre>';

    				echo 'Содержимое массива $_FILES: <pre>';
    				print_r($_FILES);
    				echo '</pre>';


				    exit("<p><strong>Ошибка!</strong> Вы зашли в обработчик формы напрямую, поэтому нет данных для обработки.</p><p> Вы можете перейти на <a href=".$address_site."> главную страницу сайта </a> </p>");
				}

		

Для примера, попытаемся загрузить файл методом POST, размер которого превышает значение 20MB.

Загрузка большого файла методом POST
Загрузка большого файла методом POST

И в результате видим что суперглобальные массивы $_POST и $_FILES пустые.

Массивы $_POST и $_FILES могут быть пустыми в двух случаях:

  • Пользователь зашел через браузерную строку напрямую в обработчик
  • Пользователь отправил методом POST данные, размер которых превышает значение, указанное в параметре post_max_size

Согласно документации, мы можем определить, почему массивы $_POST и $_FILES пустые, следующим образом:

В конце значения атрибута action формы, необходимо прикрепить некий параметр, который будет выступать в качестве флага. Этот параметр будет передаваться на сервер методом GET.

		<form action="upload-one-file.php?flag=1" method="POST" enctype="multipart/form-data" class="form-inline md-form">
	

Соответственно, на стороне сервера, внутри проверки существования ячейки 'upload_image' в массиве $_POST, мы можем сделать проверку.

Если в суперглобальном массиве $_GET, существует параметр 'flag', значит пользователь попытался загрузить слишком большой файл, иначе, он зашел в обработчик напрямую.

Так как мы научились, вывести сообщения после отправки формы, то сообщения из проверки существования ячейки 'upload_image' в массиве $_POST, также выведем на страницу с помощью сессий.

Меняем содержимое блока

		<?php
		    if(!isset($_POST['upload_image'])){}
		?>
	

таким образом:

		<?php
		    if(!isset($_POST['upload_image'])){

		        if(isset($_GET['flag'])){
		            // Сохраняем в сессию сообщение об ошибке.
		            $_SESSION["server_messages"] = "<p class='text-danger font-weight-bold'>Ошибка! Размер загруженного изображения превышает 3MB </p>";

		        }else{

		            // Сохраняем в сессию сообщение об ошибке.
		            $_SESSION["server_messages"] = "<p class='text-danger font-weight-bold'>Ошибка! Вы зашли в обработчик формы напрямую, поэтому нет данных для обработки. </p>";
		        }

		        //Возвращаем пользователя обратно на страницу загрузки изображения
		        header("Location: ".$address_site);

		        exit();
		    }
		?>
	

Теперь, если пользователь пытается загрузить на сервер файл, размер которого превышает значение, указанное в параметре post_max_size, то в результате он увидит ошибку о том, что, размер загруженного файла превышает 3MB.

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

Допустим домен нашего сайта вместе с протоколом это: http://kak-zagruzit-fajly-na-server.local/ .

Ссылка на обработчик формы, это: http://kak-zagruzit-fajly-na-server.local/upload-one-file.php

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

Переход в обработчик напрямую
Ошибка в результате перехода в обработчик напрямую

А также пользователь может перейти напрямую в обработчик, передав параметр 'flag': http://kak-zagruzit-fajly-na-server.local/upload-one-file.php?flag

В таком случае, пользователь увидит сообщение о том, что размер загруженного файла, превышает 3MB. Но по факту, он не загрузил никакого файла, он просто перешел по ссылке http://kak-zagruzit-fajly-na-server.local/upload-one-file.php?flag

Для того чтобы вывести соответствующие сообщение о том, что нет данных для обработки, необходимо определить, как пользователь зашел в обработчик. Он отправил форму или зашел напрямую.

Для этого нам поможет ячейка HTTP_REFERER из суперглобального массива $_SERVER.

Данная ячейка содержит информацию откуда пришел пользователь.

Если пользователь перешел в обработчик напрямую, то ячейка HTTP_REFERER, будет пустой, иначе в ней будет содержится адрес страницы с формой загрузки файла. В нашем случае это http://kak-zagruzit-fajly-na-server.local/.

Значит к проверке

		<?php
		    if(isset($_GET['flag']))
		?>
	

добавляем еще одно условие

		<?php
		    !empty($_SERVER['HTTP_REFERER'])
		?>
	

В результате мы имеем такую проверку:

		<?php
		    if(isset($_GET['flag']) && !empty($_SERVER['HTTP_REFERER'])
		?>
	

Теперь, если пользователь переходит в обработчик напрямую по ссылке http://kak-zagruzit-fajly-na-server.local/upload-one-file.php?flag, то в результате он получает ошибку о том что нет данных для обработки.

Как определить, что значение upload_max_filesize было превышено?

Далее, необходимо определить ошибку о том, что превышено значение, указанное в upload_max_filesize.

Для этого попытаемся загрузить файл размер которого превышает 10MB, но не достигает 20MB.

Если размер файла превышает значение, указанное в параметре upload_max_filesize, то в ячейке errors из массива с данными о загруженном файле появляется значение 1.

Также в таком случае отсутствует MIME-тип файла и адрес к временной папке, а в значение ячейки size, появляется 0.

Для того чтобы убедиться в этом, в файле upload-one-file.php до проверки существования ячейки 'upload_image' в массиве $_POST, выведем содержимое суперглобального массива $_FILES.

		<?php

		    echo '<pre>';
			print_r($_FILES);
			echo '</pre>';

		?>
	
содержимое массива $_FILES
Содержимое массива $_FILES при возникновения ошибки upload_max_filesize

Теперь, удаляем код, который выводит содержимое суперглобального массива $_FILES и обновляем страницу.

		<?php

		    echo '<pre>';
			print_r($_FILES);
			echo '</pre>';

		?>
	

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

Это случается из-за того, что отсутствует значение в ячейки type. А у нас в коде существует такая проверка:

		<?php

		    if(!in_array($_FILES['file_img']['type'], $allow_types))

		?>
	

Так как, ячейка type пустая, то ее значение не находится в массиве $allow_types, и в результате получаем эту ошибку.

Перемещаем загруженный файл в нужную папку

Для начало, в папку проекта, создадим папку 'images' в которой будем хранить загруженные изображения.

Как было сказано выше, изначально загруженный файл добавляется в некоторое временное хранилище. Адрес которой указано в ячейке tmp_name из суперглобального массива $_FILES.

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

Делается это с помощью функции move_uploaded_file($parametr1, $parametr2).

В первом параметре указываем адрес откуда хотим переместить файл, а во втором параметре указываем адрес куда хотим переместить файл.

В адресе из второго параметра необходимо указать и название файла.

Формируем название файла

И здесь хочу обратить внимание на один момент.

Допустим некий пользователь, загрузил на сервер какое-то изображение с собакой, файл которой имеет название dog.jpg.

Потом, другой пользователь, загрузил какое-то изображение с другой собакой, файл которой также имеет название dog.jpg.

Для примера, я создал две папки. В каждой папки добавил по изображению с названием dog.jpg.

Картинки пользователей
Два пользователя хотят загрузить изображения с именем dog
Согласно документации, если на сервере уже существует файл с названием dog.jpg, то при загрузки файла с таким же именем, функция move_uploaded_file() перезапишет первый файл.

Поэтому, при перемещении файла с временной папки в нужную папку, необходимо сделать название файла уникальным. Например, добавить в конце названия файла, метку текущей времени в секундах. Делается это с помощью функции time().

В нашем случае указываем что хотим переместить файл из временного хранилища в папку images.

После проверки размера загруженного файла, необходимо получить название этого файла. Делается это с помощью функции pathinfo().

		<?php

		    // Узнаем название загруженного файла
			$file_name =  pathinfo( $_FILES['file_img']['name'], PATHINFO_FILENAME );

		?>
	

Теперь, вызываем функцию move_uploaded_file().

		<?php

		    // Перемещаем изображение в нужную папку
			$result_move = move_uploaded_file($_FILES['file_img']['tmp_name'], 'images/'.$file_name.'_'.time().'.'.$extension_file);

		?>
	

В случае успешной загрузки, функция move_uploaded_file() возвращает true, иначе false.

Теперь необходимо отправить пользователя обратно на страницу и вывести ему соответственное сообщение, загружен ли файл успешно или нет.

		<?php

		    // Перемещаем изображение в нужную папку
			$result_move = move_uploaded_file($_FILES['file_img']['tmp_name'], 'images/'.$file_name.'_'.time().'.'.$extension_file);

		?>
	

Теперь необходимо отправить пользователя обратно на страницу и вывести ему соответственное сообщение, загружен ли файл успешно или нет.

		<?php

		    if(!$result_move){

		        // В случае возникновения какой-то ошибки при загрузке файла

		        // Сохраняем в сессию сообщение об ошибке.
		        $_SESSION["server_messages"] = "<p class='text-danger font-weight-bold'> Ошибка! Не удалось загрузить файл </p>";

		        //Возвращаем пользователя обратно на страницу загрузки изображения
		        header("Location: ".$address_site);

		        //Останавливаем скрипт
		        exit();
		    }

		    // Если загрузка файла было выполнено успешно, выводим пользователю соответствующее сообщение

		    // Сохраняем в сессию сообщение об ошибке.
		    $_SESSION["server_messages"] = "<p class='text-success font-weight-bold'> Файл загружен успешно! </p>";

		    //Возвращаем пользователя обратно на страницу загрузки изображения
		    header("Location: ".$address_site);

		    //Останавливаем скрипт
		    exit();

		?>
	
Файл успешно загружен на сервер
Файл успешно загружен на сервер

Готово, функционал загрузки файла на сервер реализован.

Как вывести на страницу загруженные изображения

Теперь, после того как загрузили изображение на сервер, мы хотим вывести ее на страницу.

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

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

Но, так как у нас отсутствует функционал аутентификации, то мы просто выведем все загруженные изображения из папки images.

Для этого в файле index.php, перед тем как закрыть тег div с классом container, открываем php и пишем следующий код:

		<?php

			// Получаем список изображений из папки images
		    // отсортированные по имени, в альфабетном порядке
		    $uploaded_files = scandir('images');

		    // избавляемся от точек в результате
		    $uploaded_files = array_diff($uploaded_files, ['.', '..']);

		    if(count($uploaded_files) > 0){

		    	// Если в папке находятся какие-то изображения, то выводим их на страницу
		?>
				<h2 class="mb-3">Загруженные изображения</h2>

				<div class="row mb-3">

		<?php
    				$i = 1;
            		foreach($uploaded_files as $file){
		?>
        				<div class="col-md-4 text-center">
                        	<img src="images/<?=$file?>" alt="Image" width="300" class="img-responsive" />
                    	</div>

        <?php
        			    if($i % 3 === 0){
        ?>

            				</div>
            				<div class="row mb-3">
        <?php
		        	    }

    	            	$i++;
    	        	}
        ?>
        		</div>

        <?php

		    }

        ?>

	

Переходим к тестированию реализованного функционала.

Загружаем некие изображения, смотрим добавились ли они в папку images и проверяем, выводятся ли они на страницу.

Вот что у нас получилось в результате:

Как загрузить изображения на сервер
Файл успешно загружен на сервер

На этом все. Теперь Вы знаете как загрузить файлы на сервер и как вывести загруженные изображения на страницу.

Также можно почитать:

Понравилась статья?

Тогда поделитесь ею с друзьями и подпишитесь на новые интересные статьи.

Поделиться с друзьями:

Подписаться на новые статьи:

Delivered by FeedBurner

Поддержите пожалуйста мой проект!

%next_previous_article%

Если у Вас есть какие-то вопросы или предложения, то можете писать их в комментариях или мне на почту sergiu1607@gmail.com. И если Вы заметили какую-то ошибку в статье, то прошу Вас, сообщите мне об этом, и в ближайшее время я всё исправлю.

Добавляйтесь ко мне в друзья в:

Добавляйтесь в мои группы:

Подпишитесь на мои каналы:

Автор статьи: Мунтян Сергей

Копирование материалов с сайта sozdatisite.ru ЗАПРЕЩЕНО!!!

Дата добавления: %date%