Работа с объектом FormData
10.08.2018
Теги: AJAX • FormData • JavaScript • jQuery • POST • Web-разработка • XmlHttpRequest • Форма
Объект FormData предназначен для кодирования данных, которые необходимо отправить на сервер посредством технологии AJAX (XmlHttpRequest
). Для кодирования данных метод FormData
использует формат multipart/form-data
. Это означает то, что можно подготовить для отправки по AJAX не только текстовые данные, но и файлы (input
с атрибутом type="file"
).
FormData
, необходимо осуществлять посредством метода POST.
Представить себе объект FormData
можно как набор пар «ключ-значение». Другими словами, как некоторую коллекцию элементов, в которой каждый из них представлен в виде ключа и значения (массива значений).
Работа с объектом FormData
начинается с его создания:
// создание объекта FormData var formData = new FormData();
При создании объекта FormData
ему можно в качестве параметра указать DOM-форму. В этом случае в объект FormData автоматически добавятся все поля (поле:значение) этой формы.
// создание объекта FormData и добавление в него всех полей формы var formData = new FormData(document.forms.subscribe);
После создания объекта FormData
можно использовать его методы. Один из наиболее используемых методов — это append()
. Этот метод добавляет в объект FormData
новую порцию данных (ключ-значение). При этом, если указанного ключа нет в объекте, то данный метод добавит в FormData
новый элемент «ключ-значение».
formData.append('key', 'some value');
В противном случае, если указанный ключ есть уже у объекта FormData
, то данный метод запишет его значение в качестве следующего значения этого ключа. После этого с указанным ключом уже будет связано несколько значений (массив значений).
formData.append('key', 'other value'); // 'key': ['some value', 'other value']
Другой метод для добавления данных в объект FormData
– это set()
. Отличается от append()
только тем, что не добавляет ещё одно значение для ключа (если оно уже есть). Он просто изменяет текущее значение.
formData.set('key','another value'); // 'key': 'another value'
Для удаления данных из объекта FormData
предназначен метод delete()
. Он убирает элемент из объекта FormData
по имени ключа.
formData.delete('key');
Метод has()
позволяет поверить в объекте FormData
существования указанного ключа.
// вернёт true, если в FormData есть элемент с ключом // key; в противном случае он вернёт значение false formData.has('key');
Если необходимо узнать значение, связанное с ключом, то можно воспользоваться методом get()
. Если с ключом связано несколько значений, то данный метод вернёт первое из набора. Кроме метода get()
, есть ещё метод getAll()
. Он позволяет получить массив значений, связанных с указанным ключом.
// возвращает первое значение, связанное с ключом key formData.get('key'); // возвращает массив значений, связанных с ключом key formData.getAll('key');
Отправка данных формы
Рассмотрим простой AJAX пример, в котором разберём, как применять объект FormData
для кодирования данных формы. Данный пример будет выполнять следующие основные действия:
- отправлять HTML форму на сервер методом POST (подготавливать данные для отправки запроса будем с помощью объекта FormData);
- обрабатывать данные формы на сервере посредством php и формировать на основании них ответ в формате JSON;
- получать ответ от сервера и выводить его после некоторой обработки посредством JavaScript на страницу.
Разработку этого примера начнём с создания HTML формы и контейнера для вывода результата.
<!doctype html> <html> <head> <meta charset="utf-8"> <title>FormData</title> <script src="jquery-2.1.1.min.js"></script> <script src="script.js" charset="UTF-8"></script> </head> <body> <div id="result"></div> <form action="handler.php" method="POST" id="message"> <div> <span>Имя</span> <input type="text" name="name" value=""> </div> <div> <span>Сообщение</span> <textarea name="message"></textarea> </div> <button type="submit">Отправить</button> </form> </body> </html>PHP сценарий, который будет формировать ответ клиенту в формате JSON. Для создания ответа будем использовать ключи
name
и message
суперглобального массива $_POST
.
<?php $result = array(); $result['name'] = 'Не заполнено поле name!'; $result['message'] = 'Не заполнено поле message!'; if (!empty($_POST['name'])) { $result['name'] = trim($_POST['name']); } if (!empty($_POST['message'])) { $result['message'] = trim($_POST['message']); } echo json_encode($result);
Сценарий на JavaScript, который будет кодировать данные HTML формы, отправлять её на сервер (XMLHttpRequest
), получать ответ с сервера и отображать его на странице в виде маркированного списка.
// после загрузки 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', 'handler.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>' + key + ' : ' + data[key] + '</li>'; } // добавим к переменной закрывающий тег ul output += '</ul>'; // выведем в элемент (id="result") значение переменной output document.getElementById('result').innerHTML = output; } }); // отправляем запрос на сервер request.send(formData); // отменяем отправку формы стандартным способом e.preventDefault(); }); });
Отправка формы с использованием jQuery
Объект FormData
можно также использовать в методе $.ajax()
библиотеки jQuery. Для этого методу $.ajax()
необходимо установить следующие параметры:
processData: false,
contentType: false,
Параметр processData
со значением false
предотвратит автоматическое преобразование данных FormData
в строку запроса. А параметр contentType
со значением false
запретит jQuery устанавливать заголовок Content-Type
и оставит это действие объекту XMLHttpRequest
. Установка этих параметров позволит предотвратить преобразование данных, закодированных объектом FormData
и установку неверного заголовка (application/x-www-form-urlencoded
).
Перепишем представленный выше код JavaScript с помощью методов библиотеки jQuery:
$(document).ready(function() { // при нажатии на кнопку «Отправить» $('#message').submit(function(e) { // создадим объект FormData и добавим в него данные из формы; // обратите внимание, передаем конструктору DOM-объект формы var formData = new FormData($('#message')[0]); // url — адрес скрипта, на который будет отправлен запрос // data — данные, которые необходимо отправить на сервер // processData — отменить обработку данных // contentType — не устанавливать заголовок Content-Type // type — тип запроса // dataType — тип данных ответа сервера // success — функция, которая будет выполнена после удачного запроса $.ajax({ url: 'handler.php', data: formData, processData: false, contentType: false, type: 'POST', dataType: 'JSON', success: function(data) { var output = '<ul>'; $.each(data, function(key, value) { output += '<li>' + key + ' : ' + value + '</li>'; }); output += '</ul>'; $('#result').html(output); } }); // отменяем отправку формы стандартным способом e.preventDefault(); }); });
Отправка файлов на сервер
Рассмотрим ещё один пример, в котором объект FormData
будем использовать для отправки файла на сервер.
<!doctype html> <html> <head> <meta charset="utf-8"> <title>FormData</title> <script src="jquery-2.1.1.min.js"></script> <script src="script.js" charset="UTF-8"></script> </head> <body> <div id="result"></div> <div> Выберите файл <input type="file" id="file"> </div> <button id="button">Загрузить</button> </body> </html>
Сценарий php, выполняющий сохранение загруженного файла.
<?php // переменная для хранения результата $result = 'Файл не был загружен на сервер'; // если файл был успешно загружен if ($_FILES['file']['error'] == UPLOAD_ERR_OK) { // получаем расширение исходного файла $ext = strtolower(pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION)); // получаем уникальное имя под которым будет сохранён файл $name = md5(uniqid('', true)).'.'.$ext; // перемещаем файл из временного хранилища в указанную директорию if (move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/'.$name)) { // записываем в переменную $result ответ $result = 'Файл загружен и доступен по адресу uploads/'.$name; } else { // записываем в переменную $result сообщение о том, что произошла ошибка $result = 'Ошибка при загрузке файла на сервер'; } } // возвращаем результат (ответ сервера) echo $result;
JavaScript сценарий, который отправляет файл на сервер, получает от него ответ и выводит его на странице.
// после загрузки DOM модели document.addEventListener('DOMContentLoaded', function() { // при нажатию на кнопку upload-image document.getElementById('button').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', 'handler.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 = 'Не выбран файл для загрузки!'; } }); });
JavaScript сценарий, переработанный с использованием методов библиотеки jQuery.
$(document).ready(function() { // при нажатии на кнопку «Отправить» $('#button').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]); // url — адрес, содержащий php сценарий, который будет обрабатывать запрос // processData — параметр, с помощью которого отключим преобразование данных в строку запроса // contentType — параметр, с помощью которого отключим установление типа контента jQuery // type — параметр, с помощью которого установим POST в качестве метода отправки запроса // success — функция, которая будет выполнена после удачного запроса $.ajax({ url: 'handler.php', data: formData, processData: false, contentType: false, type: 'POST', success: function(data) { result.html(data); } }); } else { result.html('Не выбран файл для загрузки!'); } }); });
- Магазин на Laravel 7, часть 19. Панель управления, добавляем редактор для страниц сайта
- AJAX. Основы передачи данных
- React.js. Начало работы. Часть 7 из 12
- WordPress. Обработка POST-запросов. Часть 2
- WordPress. Загрузка файлов. Часть 3 из 3
- WordPress. Загрузка медиа-файлов
- Yii2. Отправка данных AJAX
Поиск: AJAX • FormData • JavaScript • POST • Web-разработка • XmlHttpRequest • jQuery • Форма