Урок 19: Загрузка файлов на сервер через PHP

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

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

Настройка HTML-формы

Для загрузки файлов нужна специальная HTML-форма. Вот ключевые моменты:

  1. Метод отправки: POST (GET не подходит, так как ограничен длиной URL).
  2. Атрибут enctype: Должен быть multipart/form-data. Без него файлы не отправятся!
  3. Поле для файла: <input type="file" name="myfile">.

Пример формы:

<form action="upload.php" method="post" enctype="multipart/form-data">
  <label>Выберите файл:</label>
  <input type="file" name="userfile">
  <input type="submit" value="Загрузить">
</form>

Обработка файлов в PHP

После отправки формы данные о файле попадают в суперглобальный массив $_FILES. Его структура:

$_FILES['userfile'] = [
  'name' => 'photo.jpg',      // Имя файла
  'type' => 'image/jpeg',     // MIME-тип
  'tmp_name' => '/tmp/php123', // Временный путь
  'error' => 0,               // Код ошибки
  'size' => 10240             // Размер в байтах
];

Основные шаги обработки:

  1. Проверить, был ли файл загружен:
if (!isset($_FILES['userfile'])) {
  die('Файл не был отправлен.');
}
  1. Обработать ошибки:
if ($_FILES['userfile']['error'] !== UPLOAD_ERR_OK) {
  switch ($_FILES['userfile']['error']) {
    case UPLOAD_ERR_INI_SIZE:
      die('Файл слишком большой.');
    // ... другие коды ошибок
  }
}
  1. Проверить тип и размер файла:
$allowedTypes = ['image/jpeg', 'image/png'];
$maxSize = 2 * 1024 * 1024; // 2 МБ

if (!in_array($_FILES['userfile']['type'], $allowedTypes)) {
  die('Недопустимый тип файла.');
}

if ($_FILES['userfile']['size'] > $maxSize) {
  die('Файл превышает допустимый размер.');
}
  1. Переместить файл в постоянную директорию:
$uploadDir = __DIR__ . '/uploads/';
$filename = uniqid() . '_' . basename($_FILES['userfile']['name']); // Защита от перезаписи

if (!move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadDir . $filename)) {
  die('Ошибка при сохранении файла.');
}

echo 'Файл успешно загружен!';

Безопасность это важно!

  • Переименовывайте файлы: Используйте uniqid() или хеши, чтобы избежать перезаписи.
  • Ограничивайте типы файлов: Не доверяйте MIME-типу из $_FILES — проверяйте реальный тип через finfo_file().
  • Устанавливайте лимит размера: Настройте upload_max_filesize в php.ini.

Пример проверки реального MIME-типа:

$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($_FILES['userfile']['tmp_name']);
if (!in_array($mime, $allowedTypes)) {
  die('Обнаружен поддельный MIME-тип!');
}

Практические задачи

Задача 1: Загрузка аватара

Создайте форму для загрузки аватара пользователя. Требования:

  • Только JPEG/PNG.
  • Максимум 1 МБ.
  • Автоматическое переименование файла.

Решение:

// Код обработчика upload.php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $allowed = ['image/jpeg', 'image/png'];
  $maxSize = 1024 * 1024;

  if (!in_array($_FILES['avatar']['type'], $allowed) || $_FILES['avatar']['size'] > $maxSize) {
    die('Недопустимый файл.');
  }

  $newName = 'avatar_' . uniqid() . '.jpg';
  move_uploaded_file($_FILES['avatar']['tmp_name'], __DIR__ . '/uploads/' . $newName);
}

Задача 2: Множественная загрузка

Доработайте форму, чтобы можно было загружать до 5 файлов одновременно.

Подсказка:

<input type="file" name="files[]" multiple>

Обработка в PHP:

foreach ($_FILES['files']['tmp_name'] as $key => $tmpName) {
  // Проверяем каждый файл
}

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

Полный курс по PHP для начинающих, освойте веб-разработку с нуля!