Отправка Данных Формы Используя Fetch API
Fetch API — это современный подход для создания асинхронных запросов. Рассмотрим, как отправить данные формы на сервер, используя Fetch API. Научимся отправлять файл вложением (прикреплять к письму файл) вместе с другими полями формы.
- Что такое fetch().
- Отправка формы с помощью Fetch API.
- Fetch API FormData.
- Fetch API JSON (application/json).
- Отправка файлов (изображений) с помощью Fetch API (multipart/form-data).
1. Fetch API
Метод fetch() позволяет создавать асинхронные запросы наподобие ajax(). Сравним синтаксис jQuery AJAX и Fetch API на примере отправки данных на сервер.
jQuery AJAX:
$.ajax({
url: "handler.php",
type: "POST",
data: data
}).done(function (data) {
...
}).fail(function () {
...
});
Синтаксис fetch():
fetch("handler.php", {
method: "POST",
body: data
}).then(function (response) {
...
}).catch(function (error) {
...
});
ES6+
fetch("handler.php", {
method: "POST",
body: data
})
.then(response => ...)
.catch(error => console.error(error));
Async/Await
(function () {
getResource("/handler.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 type="submit">Отправить</button>
</form>
Напишем универсальный JavaScript код, чтобы отправка данных на сервер работала для всех форм на сайте.
2.1 Fetch API FormData
Отправим данные, используя объект FormData.
В данном случае форма будет отправлена с заголовком Content-Type: form/multipart.
document.addEventListener("DOMContentLoaded", () => {
const ajaxSend = async (formData) => {
const response = await fetch("mail.php", {
method: "POST",
body: formData
});
if (!response.ok) {
throw new Error(`Ошибка по адресу ${url}, статус ошибки ${response.status}`);
}
return await response.text();
};
if (document.querySelector("form")) {
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
$project_name = trim($_POST["project_name"]);
$admin_email = trim($_POST["admin_email"]);
$form_subject = trim($_POST["form_subject"]);
$c = true;
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 "Ошибка. Данные не отправлены.";
};
Используя данный php-обработчик, необходимо в HTML файле в теге form добавить 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))
};
if (document.getElementsByTagName("form")) {
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);
})
.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.
Поделиться с друзьями:
Статьи из данной категории:
Комментарии (10)
- Ольга
- Only to top
- Константин
- Only to top
- Владислав
- Андрей Агеев
- Ренат
- СтощийСтоящий
- Tracktor
- Евгения