- Операторы
- Управляющие инструкции
- JS Объекты
- браузер BOM
- HTML DOM
- События
- HTML Объекты
- Промисы, async/await
- Сетевые запросы
- XMLHttpRequest
- Объекты URL
- Объект formData
- Fetch API
- Fetch API 2
- Бинарные данные и файлы
- Разное
Объект formData
Объекты FormData позволяют вам легко конструировать наборы пар ключ-значение, представляющие поля формы и их значения, которые в дальнейшем можно отправить с помощью Fetch
или XMLHttpRequest
FormData
использует такой же формат на выходе, как если бы мы отправляли обыкновенную форму с encoding
установленным в "multipart/form-data"
.
Конструктор:
let formData = new FormData([form]);
Если передать в конструктор элемент HTML-формы form
, то создаваемый объект автоматически прочитает из неё поля.
Его особенность заключается в том, что методы для работы с сетью, например fetch
, позволяют указать объект FormData
в свойстве тела запроса body
.
Он будет соответствующим образом закодирован и отправлен с заголовком Content-Type: form/multipart
.
То есть, для сервера это выглядит как обычная отправка формы.
Отправка простой формы
Давайте сначала отправим простую форму.
Как вы видите, код очень компактный:
<form id="formElem"> <input type="text" name="name" value="John"> <input type="text" name="surname" value="Smith"> <input type="submit"> </form> <p id="msg"></pm> <script> formElem.onsubmit = async (e) => { e.preventDefault(); let response = await fetch('xhr/f1.php?n=1', { method: 'POST', body: new FormData(formElem) }); document.getElementById("msg").innerHTML = await response.text(); }; </script>
В этом примере серверный код не представлен, он принимает POST-запрос с данными формы и отвечает сообщением «Пользователь сохранён».
Методы объекта FormData
С помощью указанных ниже методов мы можем изменять поля в объекте FormData
:
formData.append(name, value) – добавляет к объекту поле с именем
name
и значениемvalue
,formData.append(name, blob, fileName) – добавляет поле, как будто в форме имеется элемент
<input type="file">
, третий аргументfileName
устанавливает имя файла (не имя поля формы), как будто это имя из файловой системы пользователя,formData.delete(name) – удаляет поле с заданным именем
name
,formData.get(name) – получает значение поля с именем
name
,formData.has(name) – если существует поле с именем
name
, то возвращаетtrue
, иначеfalse
Технически форма может иметь много полей с одним и тем же именем name
, поэтому несколько вызовов append
добавят несколько полей с одинаковыми именами.
Ещё существует метод set
, его синтаксис такой же, как у append
. Разница в том, что .set
удаляет все уже имеющиеся поля с именем name
и только затем добавляет новое. То есть этот метод гарантирует, что будет существовать только одно поле с именем name
, в остальном он аналогичен .append
:
- formData.set(name, value),
- formData.set(name, blob, fileName).
Поля объекта formData
можно перебирать, используя цикл for..of
:
let formData = new FormData(); formData.append('key1', 'value1'); formData.append('key2', 'value2'); var s = ''; // Список пар ключ/значение for(let [name, value] of formData) { s += `${name} = ${value}\n`; // key1=value1, потом key2=value2 } alert(s);
Отправка формы с файлом
Объекты FormData
всегда отсылаются с заголовком Content-Type: form/multipart
, этот способ кодировки позволяет отсылать файлы. Таким образом, поля <input type="file">
тоже отправляются, как это и происходит в случае обычной формы.
Пример такой формы:
<h4>Отправка формы с с файлом</h4> <form id="formElem"> <input type="text" name="firstName" value="John"> Картинка: <input type="file" name="picture" accept="image/*"> <input type="submit"> </form> <p id="msg"></pm> <script> formElem.onsubmit = async (e) => { e.preventDefault(); let response = await fetch('xhr/f1.php?n=2', { method: 'POST', body: new FormData(formElem) }); document.getElementById("msg").innerHTML = await response.text(); }; </script>
Отправка формы с Blob-данными
В примере ниже посылается изображение из <canvas>
и ещё несколько полей, как форма, используя FormData
:
<h4>Отправка формы с Blob-данными</h4> <canvas id="canvasElem" width="256" height="192" style="border:1px solid"></canvas> <input type="button" value="Отправить" onclick="submit()"> <p id="msg"></pm> <script> canvasElem.onmousemove = function(e) { let ctx = canvasElem.getContext('2d'); ctx.lineTo(e.clientX, e.clientY); ctx.stroke(); }; async function submit() { let imageBlob = await new Promise(resolve => canvasElem.toBlob(resolve, 'image/png')); let formData = new FormData(); formData.append("firstName", "John"); formData.append("picture", imageBlob, "image.png"); let response = await fetch('xhr/f1.php?n=2', { method: 'POST', body: formData }); document.getElementById("msg").innerHTML = await response.text(); } </script>
Пожалуйста, обратите внимание на то, как добавляется изображение Blob
:
formData.append("image", imageBlob, "image.png");
Это как если бы в форме был элемент <input type="file" name="image">
и пользователь прикрепил бы файл с именем "image.png"
(3й аргумент) и данными imageBlob
(2й аргумент) из своей файловой системы.
Сервер прочитает и данные и файл, точно так же, как если бы это была обычная отправка формы.