W3docs

JavaScript FormData

JavaScript FormData API: создание объектов FormData, чтение и изменение полей с get, append, set и delete, отправка данных и файлов через fetch.

Эффективная работа с данными форм — необходимое условие создания динамичных, интерактивных веб-страниц. Именно для этого JavaScript предоставляет FormData API: он позволяет собирать поля формы, программно формировать наборы пар «ключ/значение» и отправлять их на сервер — в том числе с файлами. В этом руководстве рассматривается, что такое FormData, как создавать и читать его, все доступные методы, отправка через fetch и типичные ошибки.

Знакомство с FormData

FormData — это встроенный object JavaScript, представляющий набор пар «ключ/значение», смоделированный по образцу того, как браузер отправляет HTML-форму. Он упрощает сбор данных из HTML-форм и их асинхронную отправку на сервер с помощью Fetch API.

Почему стоит использовать его вместо обычного object?

  • Он автоматически считывает существующие поля формы — не нужно вручную извлекать value из каждого поля ввода.
  • Он поддерживает файлы и Blob-объекты, которые обычные object и JSON передавать не могут.
  • При передаче в fetch браузер автоматически устанавливает правильный Content-Type (multipart/form-data) с нужным разделителем (boundary).

Создание объектов FormData

Создайте объект FormData с помощью конструктора FormData(). Если передать элемент <form>, все именованные, активные поля этой формы будут захвачены автоматически. Содержимое можно просмотреть, перебирая метод entries(), который возвращает итератор пар [key, value]:

<script>
  function onSubmit(event) {
    event.preventDefault();
    const form = document.getElementById('myForm');
    const formData = new FormData(form);
    let results = '';
    for (const [key, value] of formData.entries()) {
      results += `${key}: ${value}\n`;
    }
    alert(results)
  }
</script>
<form id="myForm" onsubmit="onSubmit(event)">
  <input type="text" name="username" value="John Doe" />
  <input type="email" name="email" value="[email protected]" />
  <input type="submit" />
</form>

Доступ к данным формы

Прочитайте одно поле с помощью get() или переберите все поля через entries(), как показано выше. get() возвращает первое значение для ключа (или null, если его не существует):

<form id="myForm" onsubmit="onSubmit(event)">
  <input type="text" name="username" value="John Doe" />
  <input type="email" name="email" value="[email protected]" />
  <input type="submit" />
</form>
<script>
  function onSubmit(event) {
    const form = document.getElementById('myForm');
    const formData = new FormData(form);
    const username = formData.get('username');
    const email = formData.get('email');
    alert(`username: ${username}; email: ${email}`);
  }
</script>

Методы FormData

Помимо чтения существующей формы, FormData позволяет вручную формировать и изменять набор данных. На каждом экземпляре доступны следующие методы:

МетодЧто делает
append(name, value)Добавляет новое значение. Если ключ уже существует, сохраняет старое значение и добавляет ещё одно — ключ может иметь несколько значений.
set(name, value)Устанавливает значение для ключа, заменяя все существующие значения этого ключа.
get(name)Возвращает первое значение для ключа или null.
getAll(name)Возвращает array всех значений для ключа.
has(name)Возвращает true, если ключ существует.
delete(name)Удаляет все значения для ключа.
entries() / keys() / values()Итераторы по парам, ключам или значениям.

Разница между append и set — наиболее частый источник ошибок:

const fd = new FormData();
fd.append('tag', 'js');
fd.append('tag', 'web');   // append keeps both
console.log(fd.getAll('tag'));   // [ 'js', 'web' ]

fd.set('tag', 'html');     // set replaces all
console.log(fd.getAll('tag'));   // [ 'html' ]

console.log(fd.has('tag'));      // true
fd.delete('tag');
console.log(fd.has('tag'));      // false

Можно также создать FormData полностью в коде — без какой-либо формы — добавляя поля напрямую. Третий аргумент append/set задаёт имя файла, когда значением является Blob или File.

Отправка FormData через Fetch API

Распространённый сценарий использования FormData — асинхронная отправка данных формы на сервер. Передайте экземпляр FormData в качестве body запроса fetch — браузер автоматически установит Content-Type в multipart/form-data с правильным разделителем, поэтому не нужно устанавливать этот заголовок вручную:

<form id="myForm" onsubmit="onSubmit(event)">
  <input type="text" name="title" value="A title" />
  <input type="text" name="body" value="A body" />
  <input type="submit" value="Submit Post" />
</form>
<div>post id: <span id="response"></span></div>
<script>
  function onSubmit(event) {
    event.preventDefault();
    const form = document.getElementById('myForm');
    const formData = new FormData(form);
    const responseSpan = document.getElementById('response');
    fetch('https://jsonplaceholder.typicode.com/posts', {
        method: 'POST',
        body: formData
    })
      .then(response => response.json())
      .then(data => { responseSpan.innerHTML = data.id; })
      .catch(error => console.error('Error:', error));
  }
</script>
Внимание

При передаче формы в конструктор FormData он автоматически включает все поля HTML-формы, в том числе скрытые. Это может привести к непредвиденному поведению, если вы не будете осторожны, особенно при наличии в форме конфиденциальных или лишних полей.

Загрузка файлов

FormData — стандартный способ загрузки файлов, поскольку он формирует запрос multipart/form-data, способный передавать двоичное содержимое вместе с текстовыми полями. При создании FormData из формы, содержащей <input type="file"> input, выбранный файл уже включён — не нужно читать input.files и добавлять его повторно:

<form id="fileUploadForm">
    <input type="file" name="file" />
    <input type="submit" value="Upload" />
</form>
<script>
    const form = document.getElementById('fileUploadForm');
    form.addEventListener('submit', (event) => {
        event.preventDefault();
        // The file input is captured automatically from the form.
        const formData = new FormData(form);
        fetch('https://httpbin.org/post', {
            method: 'POST',
            body: formData
        })
        .then(response => response.json())
        .then(data => console.log('Upload successful:', data))
        .catch(error => console.error('Error:', error));
    });
</script>

Чтобы прикрепить файл, не являющийся частью формы — например, выбранный программно, — добавьте его явно, при необходимости указав имя файла:

const formData = new FormData();
formData.append('avatar', fileObject, 'profile.png');

FormData и URLSearchParams

Оба объекта оборачивают пары «ключ/значение», но сериализуются по-разному. Используйте FormData, когда нужно отправить файлы или тело multipart/form-data. Используйте URLSearchParams, когда у вас только текст и нужно компактное тело application/x-www-form-urlencoded (или строка запроса). Можно даже создать один из другого, если все значения являются string:

const fd = new FormData();
fd.append('q', 'cats');
fd.append('page', '2');

const params = new URLSearchParams(fd);
console.log(params.toString());   // q=cats&page=2

Заключение

FormData — универсальный и мощный инструмент для управления данными форм в JavaScript-приложениях. Будь то простые текстовые поля или сложная загрузка файлов, FormData упрощает этот процесс и предоставляет удобный интерфейс для работы с данными форм. Освоив FormData, вы сможете повысить интерактивность и отзывчивость своих веб-приложений, обеспечив пользователям бесперебойный опыт взаимодействия.

Практика

Практика
Какое из следующих утверждений является преимуществом использования object FormData в JavaScript?
Какое из следующих утверждений является преимуществом использования object FormData в JavaScript?
Was this page helpful?