FormData - Объект JavaScript для кодирования данных формы
Статья, в которой познакомимся с методом FormData и научимся его использовать для кодирования данных, которые необходимо отправить на сервер посредством технологии AJAX в формате "multipart/form-data".
Назначение объекта FormData
Объект FormData предназначен для кодирования данных, которые необходимо отправить на сервер посредством технологии AJAX (XMLHttpRequest).
Для кодирования данных метод FormData использует формат "multipart/form-data". Это означает то, что он позволяет подготовить для отправки по AJAX не только текстовые данные, но и файлы (input
с type
, равным file
).
Передачу на сервер данных, находящихся в объекте FormData, необходимо осуществлять посредством метода POST.
Структура объекта FormData
Представить себе объект FormData можно как набор пар "ключ-значение". Другими словами, как некоторую коллекцию элементов в которой каждый из них представлен в виде ключа и значения (массива значений).

Работа с объектом FormData
Работа с объектом FormData начинается с его создания:
// создание объекта FormData var formData = new FormData();
При создании объекта FormData ему можно в качестве параметра указать DOM форму. В этом случае в объект FormData автоматически добавятся все поля (имяПоля:значение
) этой формы.
// создание объекта FormData и добавлением в него всех полей формы subscribe var formData = new FormData(document.forms.subscribe);
После создания объекта FormData вы можете использовать его различные методы.
Один из наиболее используемых методов – это append
(поддерживается большинством браузеров). Этот метод добавляет в объект FormData новую порцию данных (ключ-значение). При этом если указанного ключа нет в объекте, то данный метод добавит в FormData новый элемент ("ключ-значение").
formData.append('key','value1'); //"key":"value1"
В противном случае если указанный ключ есть уже у объекта FormData, то данный метод запишет его значение в качестве следующего значения этого ключа. После этого, с указанным ключом уже будет связано несколько значений (массив значений).
formData.append('key','value2'); //"key":["value1", "value2"]
Другой метод для добавления данных в объект FormData – это set
(поддерживается не всеми браузерами). Отличается данный метод от append
только тем, что он не добавляет ещё одно значение для ключа (если оно уже есть). Он просто изменяет текущее значение.
formData.set('key','value3'); //"key":"value3"
Для удаления данных из объекта FormData предназначен метод delete
. Он убирает элемент из объекта FormData по имени ключа.
formData.delete('key');
Метод has
позволяет поверить в объекте FormData наличия указанного ключа.
// данный метод вернёт true, если в FormData есть элемент с ключом key // в противном случае он вернёт значение false formData.delete('key');
Если вам необходимо узнать значение, связанное с ключом, то можно воспользоваться методом get
. Если с ключом связано несколько значений, то данный метод вернёт первое из набора. Кроме метода get
, есть ещё метод getAll
. Он позволяет получить массив значений, связанных с указанным ключом.
// возвращает первое значение связанное с ключом key formData.get('key'); // например: "value1" // получить массив значений связанных с ключом formData.getAll('key'); // например: ["value1","value2"]
Использование FormData для кодирования данных формы
Рассмотрим простой AJAX пример, в котором разберём, как применять объект FormData для кодирования данных формы.
Данный пример будет выполнять следующие основные действия:
- отправлять HTML форму на сервер методом POST (подготавливать данные для отправки запроса будем осуществлять с помощью объекта FormData);
- обрабатывать данные формы на сервере посредством php и формировать на основании них ответ в формате json;
- получать ответ от сервера и выводить его после некоторой обработки посредством JavaScript на страницу.
Разработку этого примера начнём с создания HTML формы и контейнера для вывода результата.
<div class="container"> <div class="panel panel-danger"> <div class="panel-heading">Данные, которые пришли с сервера:</div> <!-- Контейнер для вывода результата (id = "result") --> <div class="panel-body" id="result"></div> </div> <!-- HTML форма, данные которой будем отправлять на сервер по технологии AJAX (id="message") --> <form id="message"> <div class="form-group"> <label for="name">Имя:</label> <input type="text" class="form-control" name="name"> </div> <div class="form-group"> <label for="name">Сообщение:</label> <textarea class="form-control" rows="3" name="message"></textarea> </div> <button id="send-message" class="btn btn-primary">Отправить сообщение</button> </form> </div>
PHP сценарий, который будет формировать ответ клиенту в формате JSON. Для создания ответа будем использовать ключи name
и message
суперглобального массива POST.
<?php // если в массиве $_POST есть ключ name и его значение не равно пустоте, то if ((isset($_POST['name'])) && (!empty($_POST["name"]))) { // присвоить $result['name'] значение $_POST['name'] $result['name'] = $_POST['name']; } else { // иначе, $result['name'] присвоить указанную строку $result['name'] = 'Вы не ввели поле name!'; } // если в массиве $_POST есть ключ message и его значение не равно пустоте, то if ((isset($_POST['message']))&& (!empty($_POST["message"]))) { // присвоить $result['message'] значение $_POST['message'] $result['message'] = $_POST['message']; } else { // иначе, $result['message'] присвоить указанную строку $result['message'] = 'Вы не ввели поле message!'; } // преобразовать массив $result в json, а затем вывести его с помощью echo echo json_encode($result); ?>
Сценарий на JavaScript, который будет кодировать данные HTML формы (FormData), отправлять её на сервер (XMLHttpRequest), получать ответ с сервера и отображать его на странице в виде маркированного списка.
<script> // после загрузки DOM модели document.addEventListener('DOMContentLoaded', function() { // получим форму с id = "message" var message = document.getElementById('message'); // при возникновении у формы события submit message.addEventListener('submit', function(e) { // создадим объект FormData и добавим в него данные из формы var formData = new FormData(message); // создадим объект XHR var request = new XMLHttpRequest(); // инициализирум запрос request.open('POST', 'process.php'); // при изменении состояния запроса request.addEventListener('readystatechange', function() { // если запрос завершился и код ответа сервера OK (200), то if (this.readyState == 4 && this.status == 200) { // разбираем строку json, который вернул сервер и помещаем её в переменную data var data = JSON.parse(this.responseText); // создаём переменную, в которую будем складывать результат работы (маркированный список) var output = '<ul>'; // переберём объект data for (var key in data) { output += '<li><b>' + key + "</b>: " + data[key] + '</li>'; } // добавим к переменной закрывающий тег ul output += '</ul>'; // выведем в элемент (id = "result") значение переменной output document.getElementById('result').innerHTML = output; } }); // отправляем запрос на сервер request.send(formData); // отменяем отправку формы стандартным способом e.preventDefault(); }); }); </script>
Отправка объекта FormData с помощью ajax-метода библиотеки jQuery
Объект FormData можно также использовать в методе библиотеки jQuery ajax
.
Для этого методу $.ajax
необходимо установить следующие параметры:
processData: false, contentType: false,
Параметр processData
со значением false
предотвратит автоматическое преобразование данных FormData в строку запроса. А параметр contentType
со значением false
запретит jQuery устанавливать заголовок Content-Type
и оставит это действие объекту XMLHttpRequest
. Установка этих параметров позволит предотвратить преобразование данных, закодированных объектом FormData
и установку неверного заголовка (application/x-www-form-urlencoded).
Перепишем вышепредставленный код JavaScript с помощью методов библиотеки jQuery:
<script> // после загрузки страницы $(function() { // при нажатии на кнопку "Отправить" $('#message').submit(function(e) { // создадим объект FormData и добавим в него данные из формы var formData = new FormData($('#message')[0]); // ajax-запрос (пример использования formdata в jquery): // url - адрес на который будет отправлен запрос // data - данные, которые необходимо отправить на сервер // processData - отменить обработку данных // contentType - не устанавливать заголовок Content-Type // type - тип запроса // dataType - тип данных ответа сервера // success - функция, которая будет выполнена после удачного запроса $.ajax({ url: 'process.php', data: formData, processData: false, contentType: false, type: 'POST', dataType: 'JSON', success: function(data) { var output = '<ul>'; $.each(data, function(key, value) { output += '<li><b>' + key + "</b>: " + value + '</li>'; }); output += '</ul>'; $('#result').html(output); } }); // отменяем отправку формы стандартным способом e.preventDefault(); }); }); </script>

Использование FormData для отправки файлов на сервер
Рассмотрим ещё один пример, в котором объект FormData будем использовать для отправки файла на сервер.
HTML-код, состоящий из блока (div
с id="result"
), элемента input
с типом file
и кнопки для отправки файла на сервер.
<div class="container"> <!-- Блок, в который будем выводить путь к файлу на сервере --> <p class="alert alert-info"> Результат:<br><span id="result"></span> </p> <div class="form-group"> <!-- Элемент, для выбора файла --> <input type="file" id="file"> </div> <!-- Элемент для отправки файла на сервер --> <button id="upload-image" class="btn btn-primary">Отправить</button> </div>
Сценарий php, выполняющий загрузку файла в указанную директорию.
<?php // переменная для хранения результата $result = 'Файл не был успешно загружен на сервер'; // путь для загрузки файлов $upload_path = dirname(__FILE__) . '/uploads/'; // если файл был успешно загружен, то if ($_FILES['file']['error'] == UPLOAD_ERR_OK) { // получаем расширение исходного файла $extension_file = mb_strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION)); // получаем уникальное имя под которым будет сохранён файл $full_unique_name = $upload_path . uniqid('file_', true).'.'.$extension_file; // перемещает файл из временного хранилища в указанную директорию if (move_uploaded_file($_FILES['file']['tmp_name'], $full_unique_name)) { // записываем в переменную $result ответ $result = 'Файл загружен и доступен по адресу: <b>/' . substr($full_unique_name, strlen($_SERVER['DOCUMENT_ROOT'])+1) . '</b>'; } else { // записываем в переменную $result сообщение о том, что произошла ошибка $result = "Произошла обшибка при загрузке файла на сервер"; } } // возвращаем результат (ответ сервера) echo $result; ?>
JavaScript сценарий, который отправляет файл на сервер, получает от него ответ и выводит его на странице.
<script> // после загрузки DOM модели document.addEventListener('DOMContentLoaded', function() { // при нажатию на кнопку upload-image document.getElementById('upload-image').addEventListener('click', function() { // элемент, содержащий файл выбранный пользователем var file = document.getElementById('file'); // элемент для вывода результата var result = document.getElementById('result'); // если элемент содержит файл, то if (file.files.length) { // создаём объект formData var formData = new FormData(); // добавляем в formData файл formData.append('file', file.files[0]); // создаём объект XMLHttpRequest var request = new XMLHttpRequest(); // инициализирум запрос request.open('POST', 'process.php'); // при изменении состояния запроса request.addEventListener('readystatechange', function() { // если запрос завершился и код ответа сервера OK (200), то if (this.readyState == 4 && this.status == 200) { // помещаем в элемент result результат ответа сервера result.innerHTML = this.responseText; } }); // отправляем запрос request.send(formData); } else { result.innerHTML = "Не выбран файл для загрузки!"; } }); }); </script>
JavaScript сценарий, переработанный с использованием методов бибилиотеки jQuery.
<script> // после загрузки страницы $(function() { // при нажатии на кнопку "Отправить" $('#upload-image').click(function() { // элемент, с помощью которого пользователь выбирает файл var file = $('#file'); // элемент, в который выведим ответ сервера var result = $('#result'); // если файл выбран, то if (file.prop('files').length) { // создаём объект FormData var formData = new FormData(); // добавляем в объект FormData файл formData.append('file', file.prop('files')[0]); // выполняем HTTP (AJAX) запрос // url - адрес, содержащий php скрипт, который будет обрабатывать запрос // procedData - параметр, с помощью которого отключим преобразование данных в строку запроса // contentType - параметр, с помощью которого отключим установления типа контента jQuery // type - параметр, с помощью которого установим в качестве метода отправки запроса POST // success - параметр, который $.ajax({ url: 'process.php', data: formData, processData: false, contentType: false, type: 'POST', success: function(data) { result.html(data); } }); } else { result.html("Не выбран файл для загрузки!"); } }); }); </script>

Добрый день, наверняка здесь присутствует ошибка.
Метод has позволяет поверить в объекте FormData наличия указанного ключа. // данный метод вернёт true, если в FormData есть элемент с ключом key// в противном случае он вернёт значение false
formData.delete('key');Должно быть:formData.has('key');