Отправка Данных Формы Используя Fetch API
Fetch API - это современный подход для создания асинхронных запросов. Рассмотрим, как отправить данные формы на сервер, используя Fetch API. Научимся отправлять файл вложением (прикреплять к письму файл) вместе с другими полями формы.
- 1. Что такое fetch().
- 2. Отправка формы с помощью Fetch API.
- 2.1 Fetch API FormData.
- 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 FormData
Отправим данные, используя объект FormData.
В данном случае форма будет отправлена с заголовком Content-Type: form/multipart.
document.addEventListener('DOMContentLoaded', () => {
const ajaxSend = async (formData) => {
const fetchResp = await fetch('mail.php', {
method: 'POST',
body: formData
});
if (!fetchResp.ok) {
throw new Error(`Ошибка по адресу ${url}, статус ошибки ${fetchResp.status}`);
}
return await fetchResp.text();
};
const forms = document.querySelectorAll('form');
forms.forEach(form => {
form.addEventListener('submit', function (e) {
e.preventDefault();
const formData = new FormData(this);
ajaxSend(formData)
.then((response) => {
console.log(response);
form.reset(); // очищаем поля формы
})
.catch((err) => console.error(err))
});
});
});
Обработать данные на сервере вы можете как хотите. Пример 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;
if (mail($admin_email, adopt($form_subject), $message, $headers )) {
http_response_code(200);
echo "Данные отправлены.";
} else {
http_response_code(400);
echo "Ошибка. Данные не отправлены.";
};
Используя данный обработчик, необходимо в 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 воспользуйтесь следующим кодом.
document.addEventListener('DOMContentLoaded', () => {
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)
.then((response) => {
console.log(response);
form.reset(); // очищаем поля формы
})
.catch((err) => console.error(err))
});
};
});
Тогда в mail.php необходимо добавить строчку для декодирования JSON.
$_POST = json_decode(file_get_contents("php://input"), true);
Таким образом можно отправить данные формы на почту, используя Fetch API.
2.3 Отправка файлов (изображений) с помощью Fetch API
Рассмотрим, как отправлять изображения с помощью Fetch API.
В данном примере мы будем отправлять текстовые поля с вложенным (прикреплённым) файлом, в данном случае картинкой.
<form>
<div>
<label for="some_text">Введите текст</label>
<input type="text" name="Текстовое поле" id="some_text">
</div>
<div>
<label for="email">Введите email</label>
<input type="text" name="E-mail" id="email">
</div>
<div>
<label for="file_attach">Выберите изображение для загрузки.</label>
<input type="file" name="file_attach" id="file_attach">
</div>
<button type="submit">Отправить</button>
<input type="hidden" name="admin_email" value="Почта админа">
<input type="hidden" name="form_subject" value="Отправка файла Fetch API">
</form>
JavaScript.
document.addEventListener('DOMContentLoaded', () => {
const file_attach = document.getElementById('file_attach'); // файл
const forms = document.querySelectorAll('form'); // формы
const message = {
loading: 'Отправка...',
success: 'Спасибо. Форма отправлена',
failed: 'Что-то пошло не так...'
};
// обработчик события 'change' (происходит после выбора файла)
file_attach.addEventListener('change', () => {
uploadFile(file_attach.files[0]);
});
// Загрузка файла
const uploadFile = (file) => {
console.log(file.name);
// провераяем тип файла
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;
}
};
// отправляем `POST` запрос
const postData = async (url, fData) => { // имеет асинхронные операции
document.querySelector('.status').innerHTML = message.loading; // в процессе
// ждём ответ, только тогда наш код пойдёт дальше
let fetchResponse = await fetch(url, {
method: 'POST',
body: fData
});
// ждём окончания операции
return await fetchResponse.text();
};
if (forms) {
forms.forEach(el => {
el.addEventListener('submit', function (e) {
e.preventDefault();
// Блок со статусом отправки
let statusMessage = document.createElement('div');
statusMessage.classList.add('status');
el.appendChild(statusMessage);
// создание объекта FormData
const fData = new FormData(el);
fData.append('file_attach', file_attach.files[0]); // добавляем файл в объект FormData()
// Отправка на сервер
postData('/send_pultipart.php', fData)
.then(fetchResponse => {
statusMessage.innerHTML = message.success;
})
.catch(() => statusMessage.innerHTML = message.failed)
.finally(() => {
this.reset(); // очищаем поля формы
setTimeout(() => {
statusMessage.remove(); // удаляем статус
}, 5000);
});
});
});
};
});
Ниже рассмотрим пример обработки полученного файла и данных с помощью php. В данном примере мы предусмотрим как отправку сообщения с файлом, так и без него.
<?php
$project_name = "Форма с сайта ".$_SERVER['HTTP_REFERER'];
$admin_email = trim($_POST["admin_email"]);
$form_subject = trim($_POST["form_subject"]);
$file_attach = "";
// Если поле выбора вложения не пустое - закачиваем его на сервер
if (!empty($_FILES['file_attach']['tmp_name'])) {
$path = __DIR__ . "/upload-files/" . $_FILES['file_attach']['name']; // путь загрузки файла
if (copy($_FILES['file_attach']['tmp_name'], $path)) $file_attach = $path;
}
$c = true; // Script Foreach
foreach ( $_POST as $key => $value ) {
if ( is_array($value) ) {
$value = implode(", ", $value);
}
if (
$value != "" &&
$key != "project_name" &&
$key != "admin_email" &&
$key != "form_subject" &&
$key != "file_attach"
) {
$message .= "
" . ( ($c = !$c) ? '<tr>':'<tr style="background-color: #f8f8f8;">' ) . "
<td style='padding: 10px; border: #e9e9e9 1px solid;'><b>$key</b></td>
<td style='padding: 10px; border: #e9e9e9 1px solid;'>$value</td>
</tr>
";
}
}
$message = "<table style='width: 100%;'>
<tr>
<td style='padding:10px; border:#e9e9e9 1px solid; text-align:center' colspan='2'>
<big>$project_name</big>. $form_subject
</td>
</tr>
$message
</table>";
// Отправляем сообщение
if ( empty($file_attach) ) {
$headers = "MIME-Version: 1.0" . PHP_EOL .
"Content-Type: text/html; charset=utf-8" . PHP_EOL .
'From: '.$project_name.' <'.$admin_email.'>' . PHP_EOL .
'Reply-To: '.$admin_email.'' . PHP_EOL;
mail($admin_email, $form_subject, $message, $headers);
} else {
send_mail($admin_email, $form_subject, $message, $file_attach);
}
// Функция для отправки сообщения с вложением
function send_mail($to, $form_subject, $html, $path) {
$fp = fopen($path, "r");
if (!$fp) {
echo "Файл $path не может быть прочитан";
exit();
}
$file = fread($fp, filesize($path));
fclose($fp);
$boundary = "--".md5(uniqid(time())); // генерируем разделитель
$headers = "MIME-Version: 1.0\n";
$headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\n";
$multipart = "--$boundary\n";
$multipart .= "Content-Type: text/html; charset='utf-8'\n";
$multipart .= "Content-Transfer-Encoding: Quot-Printed\n\n";
$multipart .= "$html\n\n";
$message_part = "--$boundary\n";
$message_part .= "Content-Type: application/octet-stream\n";
$message_part .= "Content-Transfer-Encoding: base64\n";
$message_part .= "Content-Disposition: attachment; filename = \"".$path."\"\n\n";
$message_part .= chunk_split(base64_encode($file))."\n";
$multipart .= $message_part."--$boundary--\n";
if (!mail($to, $form_subject, $multipart, $headers)) {
echo "К сожалению, письмо не отправлено";
exit();
}
}
Если вам понравилась статья, то рекомендую к прочтению: Как передать данные из одной формы в другую
Надеюсь, вам понравилась данная информация. Если вам интересна тема web-разработки, то можете следить за выходом новых статей в Telegram.
Статьи из данной категории:
Комментарии
- Комментариев пока нет.