С помощью объекта FormData можно отправить данные формы из кода JavaScript на сервер через Ajax. Рассмотрим прстейший пример. В качестве сервера, как и в прошлых статьях, будем использовать Node.js.
Сначала создадим файл app.js, который будет представлять сервер. Определим в нем самую простейшую логику:
const http = require("http"); const fs = require("fs"); http.createServer(async (request, response) => { if(request.url == "/user"){ let body = ""; // буфер для получаемых данных // получаем данные из запроса в буфер for await (const chunk of request) { body += chunk; } // для параметра name let userName = ""; // для параметра age let userAge = 0; // регулярное выражения для поиска названия и значения поля формы const exp = /Content-Disposition: form-data; name="([^\"]+)\"\r\n\r\n(\w*)/g; let formElement; while ((formElement = exp.exec(body))){ paramName = formElement[1]; // получаем имя элемента формы paramValue = formElement[2]; // получаем значение элемента формы console.log(paramName, ":", paramValue); // выводим на консоль if(paramName === "name") userName = paramValue; if(paramName === "age") userAge = paramValue; } response.end(`Your name: ${userName} Your Age: ${userAge}`); } else{ fs.readFile("index.html", (_, data) => response.end(data)); } }).listen(3000, ()=>console.log("Сервер запущен по адресу http://localhost:3000"));
Вкратце пробежимся по коду. Сначала подключаются пакеты с функциональностью, которую мы собираемся использовать:
const http = require("http"); // для обработки входящих запросов const fs = require("fs"); // для чтения файлов с жесткого диска
Для создания сервера применяется функция http.createServer(). В эту функцию передается функция-обработчик, которая вызывается каждый раз, когда к серверу приходит запрос.
Эта функция имеет два параметра: request
(содержит данные запроса) и response
(управляет отправкой ответа).
В функции-обработчике с помощью свойства request.url
мы можем получить путь к ресурсу, к которому пришел запрос. Здесь мы предполагаем, что клиент
будет отправлять форму по адресу "/user". И в начале обрабатывает запрос по этому адресу:
if(request.url == "/user"){
Для получения значений отправленной формы считываем тело запроса в переменную body:
let body = ""; // буфер для получаемых данных // получаем данные из запроса в буфер for await (const chunk of request) { body += chunk; }
Чтобы было представление, что будет содержать body после считывания тела запроса. Допустим, на форме два поля, которые называются name и age. В этом случае тело запроса будет выглядеть примерно следующим образом:
------WebKitFormBoundarya9nLzvDVEN5gPA5Q Content-Disposition: form-data; name="name" Tom ------WebKitFormBoundarya9nLzvDVEN5gPA5Q Content-Disposition: form-data; name="age" 39 ------WebKitFormBoundarya9nLzvDVEN5gPA5Q--
Здесь мы видим маркер границы ------WebKitFormBoundarya9nLzvDVEN5gPA5Q
, который определяет начало и конец тела запроса, а также отделяет значения отдельных полей формы. (Значение
маркера границы может меняться). Для каждого поля формы определяется выражение Content-Disposition: form-data;
. Затем с помощью атрибута name
указано имя поля формы.
Затем через одну строку указано значение соответствующего поля. То есть в примере выше у нас два поля формы: поле "name" со значением "Tom" и поле "age" со
значением 39.
Теперь наша задача извлечь названия и значения полей формы. Для этого используем регулярное выражение
const exp = /Content-Disposition: form-data; name="([^\"]+)\"\r\n\r\n(\w*)/g;
Далее проходим по телу запроса регулярным выражением и извлекаем все элементы формы и их значения:
while ((formElement = exp.exec(body))){ paramName = formElement[1]; // получаем имя элемента формы paramValue = formElement[2]; // получаем значение элемента формы if(paramName === "name") userName = paramValue; if(paramName === "age") userAge = paramValue; }
Стоит отметить, что это естественно неполноценный парсинг, который не учитывает многие моменты (отправку массивов, файлов и т.д.) и приведен только для демонстраниции ajax-запросов.
После получения данных запроса отправляем в ответ клиенту некоторое сообщение:
response.end(`Your name: ${userName} Your Age: ${userAge}`);
В конце с помощью функции listen() запускаем веб-сервер на 3000 порту. То есть сервер будет запускаться по адресу http://localhost:3000/
Теперь определим файл index.html, который находится в одной папке с файлом сервера app.js
и который будет представлять код клиента:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>METANIT.COM</title> </head> <body> <script> // данные для отправки const formData = new FormData(); formData.append("name", "Tom"); formData.append("age", 39); const xhr = new XMLHttpRequest(); xhr.onload = () => { if (xhr.status == 200) { console.log(xhr.responseText); } else { console.log("Server response: ", xhr.statusText); } }; xhr.open("POST", "user", true); xhr.send(formData); </script> </body> </html>
Здесь данные формы определяются вручную в виде объекта FormData. После создания объекта FormData с помощью метода add()
в него можно
добавлять отдельные свойства и их значения. Затем для отправки на сервер объект FormData в качестве аргумента методу send().
В качестве метода HTTP устанавливается метод POST.
В обработчике onload выводим полученное от сервера сообщение на консоль.
В конце перейдем в консоли к папке сервера с помощью команды cd и запустим сервер с помощью команды node server.js
C:\app>node server.js Сервер запущен по адресу http://localhost:3000
После запуска сервера мы можем перейти в браузере по адресу http://localhost:3000, нам отобразится страница, в javascript-коде которой будет выполняться POST-запрос по адресу "/user". Код javascript получит ответ от сервера и выведет его на консоль:
В примере выше данные формы определяются вручную. Но аналогичным образом можно отправлять и данные форм, которые определены в коде html. Например, изменим код страницы index.html следующим образом:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>METANIT.COM</title> </head> <body> <form id="myForm" method="post" action="/user"> <p> <label>User Name:</label><br> <input name="name" /> </p> <p> <label>User Age:</label><br> <input name="age" /> </p> <input type="submit" value="Send" /> </form> <script> // данные для отправки const myForm = document.getElementById("myForm"); myForm.addEventListener("submit", (e)=>{ e.preventDefault(); const formData = new FormData(myForm); const xhr = new XMLHttpRequest(); xhr.onload = () => { if (xhr.status == 200) { console.log(xhr.responseText); } }; xhr.open("POST", "user", true); xhr.send(formData); }); </script> </body> </html>
Здесь в коде формы определена форма с двумя полями ввода для отправки на сервер. Причем эти поля также имеют названия name и age. В коде JavaScript перехватываем отправку формы, из формы получаем объект FormData и отправляем его на сервер.