cpp

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

Рассмотрим пример использования класса FormData. Создадим документ с формой (листинг 3.15), который будет обмениваться данными с файлом ajax.php (листинг 3.16). Отправим на сервер данные текстового поля и файл, а в качестве ответа получим подтверждение в формате JSON.

Листинг 3.15. Класс FormData

<!doctype html>
<html lang="ru">
<head>
   <meta charset="utf-8">
   <meta name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no">
   <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
   <title>Класс FormData</title>
</head>
<body>
<div class="container my-3">
  <form action="ajax.php" method="POST" id="frm1"
        enctype="multipart/form-data" onsubmit="return false;">
    <div class="form-group">
      <input type="text" class="form-control"
             id="txt1" name="txt1" required>
    </div>
    <div class="form-group">
      <input type="file" id="file1" name="file1" required>
    </div>
    <button type="button" class="btn btn-primary"
            id="btnSend">Отправить методом POST</button>
  </form>
</div>
<div class="container my-3">
   <div id="div_ajax"></div>
</div>

<script>
async function sendReqPOST() {
   if ( !window.fetch ) {
      window.alert('Ваш браузер не поддерживает Fetch API');
      return;
   }
   let frm1 = document.getElementById('frm1');
   if ( !frm1.checkValidity() ) {
      window.alert('Не заполнено поле');
      return;
   }
   let formData = new FormData(frm1);
   document.getElementById('div_ajax').innerHTML = 'Загрузка...';
   try {
      let response = await fetch('/ajax.php', {
         method: 'POST',
         body: formData
      });
      if ( !response.ok ) {
         throw new Error('Статус: ' + response.status);
      }
      let json = await response.json();
      const msg = json.txt1 + '<br>' + json.file1;
      document.getElementById('div_ajax').innerHTML = msg;
      frm1.reset();
   } catch(e) {
      document.getElementById('div_ajax').innerHTML = 'Ошибка: ' + e;
   }
}
document.getElementById('btnSend').onclick = sendReqPOST;
</script>
</body>
</html>

Листинг 3.16. Исходный код файла ajax.php

<?php
// Запрещаем кеширование
header('Expires: Tue, 12 May 2020 01:00:00 GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Pragma: no-cache');
// Указываем MIME-тип и кодировку
header('Content-Type: application/json; charset=utf-8');
if ( isset($_POST['txt1']) ) {
   if ( isset($_FILES['file1']) ) {
      if ($_FILES['file1']['error'] === 0 &&
          $_FILES['file1']['size'] > 0) {
         $file1 = $_FILES['file1']['tmp_name'] . ' размер: ' .
                  $_FILES['file1']['size'] . ' название ' . 
                  $_FILES['file1']['name'];
         // Здесь перемещаем файл в нужное место
         // с помощью функции move_uploaded_file()
      }
      else $file1 = 'Не удалось загрузить файл';
   }
   else $file1 = 'Файл не отправлен';
   $txt1 = htmlspecialchars($_POST['txt1'], ENT_COMPAT, 'UTF-8');
   $file1 = htmlspecialchars($file1, ENT_COMPAT, 'UTF-8');
   $arr = array('txt1' => $txt1, 'file1' => $file1);
   echo json_encode($arr);
}
else {
   $arr = array('txt1' => 'Данные не получены', 'file1' => '');
   echo json_encode($arr);
}

В данном примере мы воспользовались возможностями HTML 5 и сделали все поля обязательными для заполнения, добавив параметр required. Для проверки заполнения поля и выбора файла используется метод checkValidity() объекта формы. Если все элементы формы успешно прошли проверку, то метод вернет значение true, в противном случае — значение false:

let frm1 = document.getElementById('frm1');
if ( !frm1.checkValidity() ) {
   window.alert('Не заполнено поле');
   return;
}

После проверки мы получаем все данные формы, передав ссылку на нее конструктору класса FormData:

let formData = new FormData(frm1);

Далее во втором параметре функции fetch() передаем объект FormData опции body. Дополнительно указываем метод POST в опции method:

let response = await fetch('/ajax.php', {
   method: 'POST',
   body: formData
});

При этом автоматически добавляется заголовок Content-Type со значением multipart/form-data, который позволяет отправить файл на сервер.

Далее проверяем успешность операции, получаем данные в формате JSON, выводим результат и очищаем все элементы формы, вызвав метод reset():

frm1.reset();

В начале файла ajax.php запрещаем кеширование, а также указываем MIME-тип и кодировку данных. Если форма отправлена, то будет существовать переменная $_POST['txt1']. Отправленный файл доступен через переменную $_FILES['file1'], где file1 это значение параметра name поля для выбора файла. Если файл загружен без ошибок, то переменная $_FILES['file1']['error'] содержит значение 0, а размер файла ($_FILES['file1']['size']) больше нуля.

Следует учитывать, что файл загружается в каталог для временных файлов. Путь к временному файлу доступен через переменную $_FILES['file1']['tmp_name']. Чтобы сохранить файл, следует переместить временный файл в нужное место с помощью функции move_uploaded_file(). Если этого не сделать, то после завершения выполнения программы временный файл будет удален. В нашем примере мы просто получаем информацию о загруженном файле, а затем отправляем ее обратно в формате JSON.

Учебник по jQuery и AJAX
Учебник по jQuery и AJAX в формате PDF

Реквизиты

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов

cpp