Отправка Данных Формы Используя Fetch API

Fetch API - это современный подход для создания асинхронных запросов. Рассмотрим, как отправить данные формы на сервер, используя Fetch API.
  • 1. Что такое fetch().
  • 2. Отправка формы с помощью Fetch API.
  • 2.1 Fetch API x-www-form-urlencoded (application/x-www-form-urlencoded).
  • 2.2 Fetch API JSON (application/json).
  • 2.3 Отправка файлов (изображений) с помощью Fetch API (multipart/form-data).

1. Fetch API

Метод fetch() позволяет создавать асинхронные запросы наподобие ajax(). Сравним синтаксис jQuery AJAX и Fetch API на примере отправки данных на сервер.

jQuery AJAX

$.ajax({
    url: 'handlerName.php',
    type: 'POST',
    data: data
}).done(function(data){
    ...
}).fail(function(){
    ...
});

Синтаксис fetch().

fetch('handlerName.php', {
    method: 'POST',
    body: data
}).then(function(response){
    ...
}).catch(function(error){
    ...
});

ES6+

fetch('handlerName.php', {
    method: 'POST',
    body: data
})
  .then(response => ...)
  .catch(error => console.error(error));

Async/Await

(function () {
    getResource('/handlerName.php')
        .then(data => response(data))
        .catch(error => console.error(error));
}());

async function getResource(url) {
    const res = await fetch(url, { // ждём ответ, только тогда наш код пойдёт дальше

        method: 'POST',
        body: data
    });

    if (!res.ok) { // код ответа не 200~

        throw new Error(`Не удалось получить ${url}, статус: ${res.status}`);
    }
    return await res.json();
}

function response(resp) {
    ...
}

2. Отправка формы с помощью Fetch API

Рассмотрим пример, как можно реализовать отправку данных формы на e-mail.

<form>
    <input type="text" name="Имя">
    <input type="tel" name="Телефон">
    <input type="email" name="E-mail">
    <textarea name="Сообщение"></textarea>
    <button>Отправить</button>
</form>

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

2.1 Fetch API x-www-form-urlencoded

В данном случае тип отправляемых данных будет application/x-www-form-urlencoded.

const ajaxSend = (formData) => {
    fetch('mail.php', { // файл-обработчик

        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded', // отправляемые данные

        },
        body: formData
    .then(response => alert('Сообщение отправлено'))
    .catch(error => console.error(error))
};

const forms = document.getElementsByTagName('form');
for (let i = 0; i < forms.length; i++) {
    forms[i].addEventListener('submit', function(e){
        e.preventDefault();
        const formData = new FormData(this);
        ajaxSend(formData);
        this.reset(); // очищаем поля формы

    });
};

Обработать данные на сервере вы можете как хотите. Пример mail.php

<?php
$method = $_SERVER['REQUEST_METHOD'];

$c = true;

$project_name = trim($_POST["project_name"]);
$admin_email  = trim($_POST["admin_email"]);
$form_subject = trim($_POST["form_subject"]);

foreach ( $_POST as $key => $value ) {
  if ( is_array($value) ) {
    $value = implode(", ", $value);
  }
  if ( $value != "" && $key != "project_name" && $key != "admin_email" && $key != "form_subject" ) {
    $message .= "
    " . ( ($c = !$c) ? '<tr>':'<tr style="background-color: #f8f8f8;">' ) . "
      <td style='padding: 10px; border: #e2dddd 1px solid;'><b>$key</b></td>
      <td style='padding: 10px; border: #e2dddd 1px solid;'>$value</td>
    </tr>
    ";
  }
}

$message = "<table style='width: 100%;'>$message</table>";

function adopt($text) {
    return '=?UTF-8?B?'.Base64_encode($text).'?=';
}

$headers = "MIME-Version: 1.0" . PHP_EOL .
"Content-Type: text/html; charset=utf-8" . PHP_EOL .
'From: '.adopt($project_name).' <'.$admin_email.'>' . PHP_EOL .
'Reply-To: '.$admin_email.'' . PHP_EOL;

mail($admin_email, adopt($form_subject), $message, $headers );

Используя данный обработчик, необходимо в HTML файле в теге form добавить 3 скрытых input'а :
1. Имя сайта
2. Почту, на которую будут приходить данные
3. Метка, с описанием места отправки формы

<input type="hidden" name="project_name" value="SiteName">
<input type="hidden" name="admin_email"  value="yourMail">
<input type="hidden" name="form_subject" value="Форма с подвала сайта SiteName">

2.2 Fetch API JSON

Чтобы отправить данные в формате JSON воспользуйтесь следующим кодом.

const ajaxSend = (formData) => {
    fetch('mail.php', { // файл-обработчик

        method: 'POST',
        headers: {
            'Content-Type': 'application/json', // отправляемые данные

        },
        body: JSON.stringify(formData)
    })
    .then(response => alert('Сообщение отправлено'))
    .catch(error => console.error(error))
};

const forms = document.getElementsByTagName('form');
for (let i = 0; i < forms.length; i++) {
    forms[i].addEventListener('submit', function(e){
        e.preventDefault();

        let formData = new FormData(this);
        formData = Object.fromEntries(formData);

        ajaxSend(formData);
        this.reset();
    });
};

Object: fromEntries на момент написания статьи поддерживает 80% браузеров. Не поддерживает IE и Edge.

Тогда в mail.php необходимо добавить строчку для декодирования JSON.

$_POST = json_decode(file_get_contents("php://input"), true);

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

2.3 Отправка файлов (изображений) с помощью Fetch API

Рассмотрим, как отправлять изображения с помощью Fetch API.

HTML.

<form>
    <div>
        <label>Выберите изображение для загрузки.</label>
        <input type="file" id="fileImage">
    </div>
    <button type="submit">Отправить</button>
</form>

JavaScript.

const input = document.getElementById('fileImage')

// обработчик события 'change' (происходит после выбора файла)

input.addEventListener('change', () => {
    uploadFile(input.files[0]);
});

const uploadFile = (file) => {

    // провераяем тип файла

    if(!['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml'].includes(file.type)) {
        alert('Разрешены только изображения.');
        return;
    }

    // проверим размер файла (<2 Мб)

    if (file.size > 2 * 1024 * 1024) {
        alert('Файл должен быть менее 2 МБ.');
        return;
    }

    // добавляем файл в объект FormData()

    const fData = new FormData();
    fData.append('avatar', file);

    // отправляем `POST` запрос

    fetch('/uploadHandler', {
        method: 'POST',
        body: fData
    })
      .then(res => res.json())
      .then(json => console.log(json))
      .catch(err => console.error(err));
}

Далее, на сервере, выполняете необходимые действия.

Если вам понравилась статья, то рекомендую к прочтению: Как передать данные из одной формы в другую

admin
27/11/2019 15:02