- Операторы
- Управляющие инструкции
- JS Объекты
- браузер BOM
- HTML DOM
- События
- HTML Объекты
- Промисы, async/await
- Сетевые запросы
- XMLHttpRequest
- Объекты URL
- Объект formData
- Fetch API
- Fetch API 2
- WebSocket
- Server Sent Events
- Бинарные данные и файлы
- Модули
- Классы
- Разное
Объект 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й аргумент) из своей файловой системы.
Сервер прочитает и данные и файл, точно так же, как если бы это была обычная отправка формы.