Загрузка файлов на сервер

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

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

Но не буду вас запугивать, а лучше представлю вашему вниманию уже готовую функцию (PHP скрипт) для проверки и загрузки файлов на сервер. Функция 100% рабочая. Я сам использую её на своих сайтах. Данная функция написана под загрузку файлов изображений (фоток) в формате .jpg, .gif, .png. Но при желании можно внести изменения, чтобы адаптировать PHP скрипт под свои нужды.

<?php
/**  
 * Функция загрузки файла (аплоадер)  
 * @param  int    $max_file_size    максимальный размер файла в мегабайтах  
 * @param  array  $valid_extensions массив допустимых расширений  
 * @param  string $upload_dir       директория загрузки  
 * @return array                    сообщение о ходе выполнения  
 */  
    $extensions = array('jpg', 'jpeg', 'png', 'gif');  
    $upload_dir = 'img_user';  // папка для загрузки (создать на сервере)

    function uploadHandle($max_file_size = 1024, $valid_extensions = array(), $upload_dir = '.')  
    {  
      
        $error = null;  
        $info  = null;  
        $max_file_size *= 1048576;  // размер файла в Mb
        if ($_FILES['file']['error'] === UPLOAD_ERR_OK)  
        {  
            // проверяем расширение файла  
            $file_extension = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);  
            if (in_array(strtolower($file_extension), $valid_extensions))  
            {  
                // проверяем размер файла  
                if ($_FILES['file']['size'] < $max_file_size)  
                {  
	      $file_name = time() . $_FILES['file']['name'];  // к имени файла добавляем метку времени, чтобы исключить одинаковые имена
                    $destination = $upload_dir .'/' . $file_name;  
      
                    if (move_uploaded_file($_FILES['file']['tmp_name'], $destination))  
                        $info = 'Файл успешно загружен';  
                    else  
                        $error = 'Не удалось загрузить файл';  
                }   
                else  
                    $error = 'Размер файла больше допустимого';  
            }   
            else  
                $error = 'У файла недопустимое расширение';  
        }   
        else  
        {  
            // массив ошибок  
            $error_values = array( 

                UPLOAD_ERR_INI_SIZE   => 'Размер файла больше разрешенного директивой upload_max_filesize в php.ini',  
                UPLOAD_ERR_FORM_SIZE  => 'Размер файла превышает указанное значение в MAX_FILE_SIZE',                            
                UPLOAD_ERR_PARTIAL    => 'Файл был загружен только частично',   
                UPLOAD_ERR_NO_FILE    => 'Не был выбран файл для загрузки',   
                UPLOAD_ERR_NO_TMP_DIR => 'Не найдена папка для временных файлов',   
                UPLOAD_ERR_CANT_WRITE => 'Ошибка записи файла на диск' 

                                  );  
      
            $error_code = $_FILES['file']['error'];  
      
            if (!empty($error_values[$error_code]))  
                $error = $error_values[$error_code];  
            else  
                $error = 'Случилось что-то непонятное';  
        }  
      
        return array('info' => $info, 'error' => $error);  
    }
?>

В php скрипте реализованы две проверки:

  1. так как хостер ограничивает размер загружаемого файла (на момент написания данного материала у меня на хостинге стоит ограничение в 8 Mb), то проверка максимального размера необходима;
  2. проверка расширения файла позволяет отсеять ненужные файлы до загрузки.

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

Теперь о том, как это реализовать практически

Помещаем PHP код функции в отдельный файл: function.php и размещаем его на сервере в корневом каталоге.

Далее создаём файл – обработчик формы загрузки пользовательского файла: upload.php

<?php
include("function.php"); // подключаем файл с функцией
    // Запускаем функцию
if(!empty($_POST['button'])) // если кнопка "button"  нажата
{    
$message = uploadHandle(8, $extensions, $upload_dir);
// Выводим сообщение 
echo $message['error'] ? $message['error'] : $message['info'];
}
?>

И создадим html-файл в котором разместим форму для загрузки фото: index.html

<form action="upload.php" enctype="multipart/form-data" method="POST" name="form_upload">
  <label>Фото :<input id="file" name="file" type="file" /></label>
  <label><input name="button" type="submit" value="Отправить" /></label>
</form>

upload.php – файл обработчик формы
name="button" – имя кнопки, при нажатии на которую запускается функция загрузки файла на сервер

Загрузка нескольких файлов

Теперь разберем случай, когда необходимо загрузить на сервер сразу несколько файлов.
Для этого нам понадобиться в файлах function.php upload.php и index.html сделать некоторые изменения.

function.php

<?php
/**  
 * Функция загрузки файла (аплоадер)  
 * @param  int    $max_file_size    максимальный размер файла в мегабайтах  
 * @param  array  $valid_extensions массив допустимых расширений  
 * @param  string $upload_dir       директория загрузки  
 * @return array                    сообщение о ходе выполнения  
 */  
    $extensions = array('jpg', 'jpeg', 'png', 'gif');  
    $upload_dir = 'img_user';  // папка для загрузки (создать на сервере)

    function uploadHandle($max_file_size = 1024, $valid_extensions = array(), $upload_dir = '.', $i = 0)  
    {  
      
        $error = null;  
        $info  = null;  
        $max_file_size *= 1048576;  // размер файла в Mb
        if ($_FILES['file']['error'][$i] === UPLOAD_ERR_OK)  
        {  
            // проверяем расширение файла  
            $file_extension = pathinfo($_FILES['file']['name'][$i], PATHINFO_EXTENSION);  
            if (in_array(strtolower($file_extension), $valid_extensions))  
            {  
                // проверяем размер файла  
                if ($_FILES['file']['size'][$i] < $max_file_size)  
                {  
	      $file_name = time() . $_FILES['file']['name'][$i];  // к имени файла добавляем метку времени, чтобы исключить одинаковые имена
                    $destination = $upload_dir .'/' . $file_name;  
      
                    if (move_uploaded_file($_FILES['file']['tmp_name'][$i], $destination))  
                        $info = 'Файл успешно загружен';  
                    else  
                        $error = 'Не удалось загрузить файл';  
                }   
                else  
                    $error = 'Размер файла больше допустимого';  
            }   
            else  
                $error = 'У файла недопустимое расширение';  
        }   
        else  
        {  
            // массив ошибок  
            $error_values = array( 

                UPLOAD_ERR_INI_SIZE   => 'Размер файла больше разрешенного директивой upload_max_filesize в php.ini',  
                UPLOAD_ERR_FORM_SIZE  => 'Размер файла превышает указанное значение в MAX_FILE_SIZE',                            
                UPLOAD_ERR_PARTIAL    => 'Файл был загружен только частично',   
                UPLOAD_ERR_NO_FILE    => 'Не был выбран файл для загрузки',   
                UPLOAD_ERR_NO_TMP_DIR => 'Не найдена папка для временных файлов',   
                UPLOAD_ERR_CANT_WRITE => 'Ошибка записи файла на диск' 

                                  );  
      
            $error_code = $_FILES['file']['error'][$i];  
      
            if (!empty($error_values[$error_code]))  
                $error = $error_values[$error_code];  
            else  
                $error = 'Случилось что-то непонятное';  
        }  
      
        return array('info' => $info, 'error' => $error);  
    }
?>

index.html

<form action="upload.php" enctype="multipart/form-data" method="POST" name="form_upload">
	<label>Фото 1:<input name="file[]" type="file" /></label><br>
    <label>Фото 2:<input name="file[]" type="file" /></label><br>
    <label>Фото 3:<input name="file[]" type="file" /></label><br><br>
    <label><input name="button" type="submit" value="Отправить" /></label>
</form>

upload.php

<?php
include("function.php"); // подключаем файл с функцией
    // Запускаем функцию
if(!empty($_POST['button'])) // если кнопка "button"  нажата
{ 
	for( $i = 0, $length = count( $_FILES['file']['name'] ); $i < $length; $i++){   
		$message = uploadHandle(8, $extensions, $upload_dir,$i);
		// Выводим сообщение 
		echo $message['error'] ? $message['error'] : $message['info'];
	}
}
?>

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

Еще одна функция, которая тесно связана с загрузкой графических файлов (фоток) – это функция для изменения размеров фотки: ImageResize.

Комментарии по теме: "Загрузка файлов на сервер".

  1. автор Ульяна

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

  2. автор Константин

    Здравствуйте. А как сделать: синхронно, загрузить файлы на сервер а имена этих файлов в базу данных?

  3. автор Дмитрий

    Здравствуйте! Можно ли данный скрипт использовать не для отправки на сервер, а для отправки на почту?

  4. автор Павел

    Спасибо, было полезно

  5. автор Дядя

    В указанном примере загружается 3 файла. Как после(или во время) загрузки дать файлам имена 1, 2 и 3(буквально, плюс расширение), соблюдая при этом последовательность формы. Т.е. файл из первого input должен быть 1, из второго 2, из 3 - 3. Добавление времени убрал, т.к. файлы должны перезаписываться.

  6. автор Евгений

    строку:
    $info = 'Файл успешно загружен';
    можно заменить на:
    $info = $file_name;
    тогда
    $message['info']; - будет имя загружаемого файла

  7. автор Евгений

    В функцию "uploadHandle" в "return" добавить переменную имени файла.
    return($file_name); , чтобы функция возвращала имя загружаемого файла.
    Имя загружаемого файла сохраняем в базе данных с соответствующим объявлением. Затем на странице выводим объявление и путь к файлу.

  8. автор Михаил

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

  9. автор Илья

    Евгений, я так и смог понять, как передать URL этой фотографии. Объясните поподробнее пожалуйста.

  10. автор Евгений

    А папку 'img_user' для загрузки на сервере создали?

  11. автор Ака

    у меня это вылазит
    Предупреждение: move_uploaded_file(img_user/1413813623fon.png): failed to open stream: нет такого файла или каталога /home/u450707151/public_html/function.php на линии 30

    Предупреждение: move_uploaded_file(): Unable to move '/tmp/phpaHa1pf' до 'img_user/1413813623fon.png' в /home/u450707151/public_html/function.php на линии 30
    Не удалось загрузить файл

  12. автор Евгений

    URL фотографии - $destination
    return $destination
    А далее вставляете URL фото куда вам надо

  13. автор Антон

    Статья очень помогла, но возник вопрос.
    Фото загружается на сервер, но как в тв-параметр передать URL этой фотографии.

  14. автор Евгений

    Большая просьба, оставлять сообщения только по данной теме. Спам, реклама и т.д. будут удаляться.

Добавить комментарий