FormData: что попадает в отправляемую форму
Какие поля попадают в FormData и почему Content-Type с multipart boundary лучше оставить браузеру.
- Элементы формыУчитываем name и состояние disabled
- FormDataСобирает участвующие в отправке поля
- FetchБраузер задаёт multipart boundary сам
На экране форма заполнена, а на сервере части значений нет. Для FormData важно не то, что видно пользователю, а имя поля, его состояние и правила отправки формы. Посмотрим на небольшой пример с файлом: какие данные войдут в запрос и какой заголовок браузер должен добавить сам.
Форма с текстом и файлом
<form id="feedback">
<input name="subject" value="Документация">
<textarea name="message">Уточните пример</textarea>
<input name="internal" value="Черновик" disabled>
<input type="file" name="attachment">
<button>Отправить</button>
</form>
<script>
document.querySelector('#feedback').addEventListener('submit', function (event) {
event.preventDefault();
const data = new FormData(event.currentTarget);
data.append('source', 'help-page');
const request = new XMLHttpRequest();
request.open('POST', '/feedback');
request.onload = function () {
console.log(request.status);
};
request.onerror = function () {
console.log('Сетевая ошибка');
};
request.send(data);
});
</script>В FormData передаётся сама форма. Отключённое поле internal не попадёт в набор. Элемент без name тоже не создаёт обычную именованную запись. Имена должны совпадать с ожидаемым сервером контрактом, а не с видимыми подписями. Дополнительный source добавляется программно и должен проходить серверную проверку наравне с другими значениями: пользователь может отправить собственный запрос.
Заголовок формирует браузер
При передаче FormData не задавайте вручную Content-Type multipart/form-data. Браузер добавляет к нему boundary, согласованный с фактическим телом. Заголовок без подходящей границы мешает серверу разобрать поля. Не преобразуйте такой набор автоматически в URLSearchParams, если в нём есть файлы: текстовая сериализация не сохраняет их содержимое. Выбор формата зависит от контракта маршрута, а не только от удобства одной строки кода.
FormData не выполняет проверку доступа и не гарантирует, что сервер принял файл. Обработчик onload срабатывает и для HTTP-ответа с ошибкой, поэтому нужно проверять status и согласованный формат ответа. Сетевая ошибка обрабатывается отдельно. Поддержку нужных методов и вариантов конструктора проверьте в браузерах, с которыми работает приложение.
Как проверить состав запроса
В панели сети сравните отправку с файлом и без него. Поля subject, message и source должны присутствовать, internal — отсутствовать. Проверьте большой файл и потерю сети, а на сервере — имена полей, ограничения размера и статус обработки. Содержимое чужих вложений для диагностики в общий журнал не записывайте.
