Что такое FormData

Содержание

Введение в FormData

FormData - это встроенный в браузер интерфейс, который позволяет собирать и отправлять данные на сервер. Он используется для асинхронной отправки данных формы, включая файлы, с помощью XMLHttpRequest или Fetch API.

Что такое FormData и как с ним работать?

Объект FormData представляет собой набор пар "ключ-значение", где ключи - это имена полей формы, а значения - данные этих полей. Когда вы вызываете formData.append(), вы добавляете новую пару ключ-значение в эту структуру.

Вы можете думать о FormData как о представлении данных HTML-формы в виде объекта JavaScript. Это упрощает сбор и отправку таких данных на сервер.

Создание экземпляра FormData через конструктор

Чтобы создать новый объект FormData, используйте:

let formData = new FormData()

Это создаст пустой объект, который вы затем можете заполнить данными с помощью метода append().

Таким образом, FormData предоставляет программный интерфейс для управления и отправки данных форм в веб-приложениях.

FormData - это встроенный в браузер объект, который позволяет легко собирать и отправлять данные в веб-приложениях.

Ключевые особенности FormData:

  • Представляет собой пары ключ-значение , где ключи - это имена полей, а значения - данные этих полей
  • Позволяет легко добавлять данные с помощью метода append()
  • Автоматически собирает данные из форм при создании объекта
  • Осуществляет передачу файлов вместе с текстовой информацией
  • Работает с XMLHttpRequest и Fetch API для асинхронной отправки данных

Как работать с FormData

// Получаем html элемент <input type="file"> с id fileInput
const fileInput = document.querySelector('#fileInput')

// Пользователь выбрал файл, и мы получаем ссылку на первый файл  
const file = fileInput.files[0]

// Добавляем файл в FormData
const formData = new FormData()
formData.append('file', file)

// Теперь файл доступен в formData по ключу 'file'

Пошагово что происходит:

  1. С помощью querySelector находим нужный элемент <input type="file"> на странице
  2. После того как пользователь выбрал файл через поле выбора, ссылка на выбранный файл становится доступной в свойстве files этого элемента input.
  3. Берём первый выбранный файл из массива fileInput.files и сохраняем в переменной file.
  4. Создаём объект FormData() и добавляем туда файл под ключом 'file' с помощью метода append()

Таким образом файл доступен в formData и готов к отправке на сервер.

При необходимости в FormData можно добавитье другие файлы и поля перед отправкой.

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

let formData = new FormData()

Добавление данных в FormData

formData.append('name', 'John')

formData.append('file', fileInput.files[0])

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

fetch('/url', {
    method: 'POST',
    body: formData
})

Удаление данных

formData.delete('key')

Проверка наличия данных

if (formData.has('key')) {
    // ...
}

Получение всех данных

formData.forEach((value, key) => {
    console.log(key, value)
})

Основные преимущества FormData:

  • Удобный интерфейс для управления формами
  • Возможность отправки файлов
  • Автоматическая сериализация данных

Таким образом, это очень полезный объект для работы с данными форм и файлами в JavaScript.

Добавление данных в FormData

Вот основные способы добавления данных в объект FormData:

Выбор файла пользователем и получение объекта File

Чтобы получить доступ к файлу из формы, можно использовать:

let file = fileInput.files[0]

Здесь file - это объект File API, содержащий выбранный файл.

Добавление файла в FormData - копирование или ссылка?

При добавлении файла через:

formData.append('file', file)

Происходит копирование бинарных данных файла в объект FormData. То есть передаётся не ссылка на файл, а его содержимое.

Размер FormData при добавлении файлов

Размер FormData увеличивается на размер добавленного файла. То есть при добавлении 1 Мб файла, размер FormData станет примерно на 1 Мб больше.

При этом сам FormData не имеет собственных данных. Он лишь инкапсулирует и транспортирует добавленные файлы и поля.

Таким образом, в FormData удобно добавлять как файлы, так и дополнительные текстовые поля перед отправкой всего на сервер.

Чтение данных из FormData

Для чтения данных из объекта FormData используются следующие основные подходы:

Чтение содержимого файла с помощью FileReader

Это API предоставляет несколько методов для чтения файлов:

const reader = new FileReader()

Методы чтения

readAsDataURL

Этот метод читает файл и кодирует его бинарные данные с использованием base64, формируя строку со специальным форматом data:[<mediatype>][;base64],<data>. Эта строка выступает в роли источника данных, её можно безопасно устанавливать в атрибут src элементов интерфейса (img, video, audio) для отображения выбранных пользователем файлов:

reader.readAsDataURL(file)

reader.onload = () => {
    // отображаем превью 
    document.querySelector('img').src = reader.result
}

Таким образом мы можем встроить предпросмотр файла в интерфейс, что удобно для отображения картинок, видео или PDF документов, выбранных пользователем перед загрузкой на сервер.

Фактически здесь не создаётся ссылка на URL, это просто строковое представление бинарных данных, удобное для встраивания файлов в web-страницы для предпросмотра.

Название "Data URL" исторически закрепилось за этим форматом, хотя на самом деле это не URL в прямом смысле.

readAsText

Для текстовых файлов (.txt, .csv):

reader.readAsText(file)
reader.onload = () => {
    // получаем текст
    console.log(reader.result)
}
readAsArrayBuffer

Низкоуровневое бинарное представление файла:

const reader = new FileReader()

reader.readAsArrayBuffer(file)

reader.onload = () => {
    const arrayBuffer = reader.result

    fetch('/upload', {
        method: 'POST',
        body: arrayBuffer
    })
}

reader.onerror = () => {
    console.error('Ошибка чтения файла')
}

ArrayBuffer представляет собой низкоуровневый доступ к бинарным данным файла.

Здесь мы читаем файл в ArrayBuffer с помощью FileReader, а затем отправляем полученные двоичные данные на сервер через fetch, установив ArrayBuffer в параметр body.

Основные моменты:

  • FileReader позволяет получить низкоуровневый доступ к бинарным данным
  • Это данные можно отправить через fetch или XMLHttpRequest
  • На сервере приходит сырой бинарный файл без дополнительной упаковки

Это подходит для таких случаев:

  • Потоковая передача аудио/видео
  • Работа с данным в памяти (обрезка изображений, парсинг двоичных форматов)
  • Отправка бинарных данных на сервер напрямую

Как видите, это более сложный и низкоуровневый API. В большинстве случаев проще использовать readAsDataURL или readAsText.

Но readAsArrayBuffer открывает путь к низкоуровневой работе с бинарными данными файлов.

Также при ошибке чтения срабатывает событие:

reader.onerror = () => {
    console.error('Ошибка чтения файла')
}

Вывод

FileReader позволяет гибко читать файлы в нужном формате для предпросмотра или отправки на сервер.

Доступность файла после удаления с диска

Файл в памяти браузера существует независимо от файла на диске. Поэтому даже если оригинальный файл удален, данные в объекте File останутся доступны.

Это позволяет выбрать файлы, обработать их в браузере, а затем отправить на сервер.

Доступ к данным через перебор

Все данные в FormData можно перебрать как обычный объект:

for (let [key, value] of formData) {
    console.log(key, value)
}

Таким образом, FormData предоставляет гибкие возможности для чтения, обработки и транспортировки данных форм и файлов в браузере.

Отправка данных из FormData

Для отправки данных из FormData на сервер используются следующие основные подходы:

От выбора файла до отправки на сервер

Основные этапы:

  1. Получение файла из <input type="file">
  2. Добавление в FormData с помощью append()
  3. Отправка через fetch/axios или XMLHttpRequest
  4. Обработка файла на сервере

Альтернативные способы отправки файлов

Вместо FormData можно отправлять:

  • Файлы напрямую через Blob или ArrayBuffer
  • В виде base64 строки
  • Через WebSockets

Но FormData в большинстве случаев проще и надёжнее.

Использование FormData с библиотекой Axios

Axios поддерживает отправку FormData. Это удобно для:

  • Отправки файлов
  • Отправки данных формы (имитация форм)

Но для простого JSON можно обойтись без FormData.

Основные преимущества

  • Удобный и надёжный способ отправки файлов и форм
  • Хорошая поддержка браузерами и серверами
  • Простота добавления данных с помощью append()

Таким образом, в большинстве случаев FormData - лучший выбор для асинхронной отправки данных формы с файлами.

Работа с файлами и FormData

При работе с файлами в формах есть несколько способов взаимодействия FormData и других интерфейсов.

Отправка одного файла через Axios без объекта FormData

Файлы можно отправлять напрямую, без FormData:

const file = fileInput.files[0]

axios.post('/upload', file)

Это простой способ для отправки одного файла.

Отправка одного файла через Fetch без объекта FormData

Вот пример отправки одного файла без использования FormData через Fetch API:

const fileInput = document.querySelector('#file')
const file = fileInput.files[0]

fetch('/upload', {
    method: 'POST',
    body: file
})
    .then(response => {
        if (!response.ok) {
            throw new Error('Ошибка загрузки файла')
        }

        // данные не нужны, просто проверяем ответ
        console.log('Файл успешно загружен')
    })
    .catch(error => {
        console.error('Ошибка:', error)
    })

Здесь ключевые моменты:

  • Получаем ссылку на элемент <input type="file">
  • Берём из него первый выбранный файл
  • Передаём файл напрямую в параметр body запроса
  • Устанавливаем method: 'POST'
  • Обрабатываем ответ сервера в блоках then/catch

Преимущества этого подхода:

  • Простота и лаконичность кода
  • Нет накладных расходов на создание FormData

Недостатки:

  • Подходит только для одного файла
  • Нет гибкости в добавлении дополнительных данных

Таким образом, для простых случаев отправки файла это хорошее решение.

Отправка нескольких файлов через Axios

Несколько файлов можно объединить в один Blob.

Blob (Binary Large Object) - это API для представления больших бинарных данных в веб-приложениях.

Основные возможности Blob:

  • Объединение данных из разных источников в один объект
  • Эффективная передача и хранение бинарных данных
  • Поддержка операций чтения/записи как с обычными объектами
  • Совместимость с FileReader, URL и другими API
const blob = new Blob([file1, file2])

axios.post('/upload', blob)

Blob часто используется для:

  • Передачи бинарных данных между сервером и клиентом
  • Генерации файлов на лету в браузере
  • Потоковой передачи данных

Таким образом Blob позволяет унифицированно работать с бинарными данными в веб-приложениях.

Но это менее гибко, чем FormData.

Когда стоит избегать FormData?

  • Нет необходимости в данных формы
  • Нужна отправка в виде JSON
  • Требуется полный контроль над данными запроса

В остальных случаях FormData является оптимальным решением.

Дополнительные возможности FormData

Помимо отправки файлов и простых данных форм, FormData реализует ряд дополнительных возможностей:

Передача больших объемов данных

По сравнению с URL-encoding, в FormData нет ограничений на:

  • Объем данных
  • Символьный состав

Применение multipart/form-data за пределами файлов

Кодирование multipart/form-data позволяет отправлять:

  • Большие объемы данных
  • Текст с нестандартными символами

Без ограничений URL-кодирования.

Ограничения кодирования www-form-urlencoded

URL-кодирование не подходит для отправки больших объёмов данных или текста с нестандартными символами, так как накладывает ограничения на размер и состав данных из соображений совместимости с форматом URL

URL-encoding неэффективен и ограничен для:

URL-кодирование данных формы с использованием application/x-www-form-urlencoded, которое является стандартным кодированием для простых HTML-форм, имеет несколько ограничений:

Бинарные данные

URL-кодирование предназначено только для текстовых данных, поэтому оно не поддерживает отправку файлов или других двоичных данных. Все данные должны быть преобразованы в текстовый формат с использованием специальных кодировок вроде base64, что неэффективно для больших объемов бинарных данных.

Нестандартные символы

URL-кодирование основано на преобразовании символов в процентные кодыUTF-8, однако некоторые символы всё равно могут вызвать проблемы или быть неверно интерпретированы сервером.

Большие объёмы данных

Кодирование значительно увеличивает объём передаваемых данных из-за расширения размера текстового представления каждого символа в 2-3 раза. К тому же обычно накладываются ограничения на длину URL от сервера или браузера.

Всё это делает application/x-www-form-urlencoded неподходящим для передачи больших объёмов данных или файлов. В таких случаях лучше использовать multipart/form-data.

Альтернативы кодирования данных форм

Возможные форматы данных:

  • JSON
  • XML
  • Произвольные типы данных

Главное — обеспечить поддержку на сервере.

Таким образом, FormData гибко расширяет возможности HTML форм для передачи данных.

FormData в контексте HTML форм

FormData может использоваться как для асинхронной отправки данных форм через JavaScript, так и с обычными HTML формами.

Необходимость FormData при использовании обычных форм

При использовании обычной HTML формы объект FormData явно создавать не нужно:

<form action="/submit" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
</form>

Браузер автоматически соберёт и закодирует данные при отправке формы.

FormData необходим при асинхронной отправке

  • Отправке формы через AJAX
  • Динамическом создании и манипулировании данными формы
  • Интеграции формы с другим интерфейсом ввода

Передача данных по частям

В формате multipart/form-data каждое поле формы и файл отправляются отдельными блоками данных с разделителями между ними в теле запроса. Это позволяет принимать как текст, так и двоичные данные.

--myBoundary

Content-Type: text/plain

--myBoundary  

Content-Disposition: form-data; name="file1"; filename="report.pdf"
Content-Type: application/pdf
<двоичные данные файла report.pdf>

--myBoundary

Content-Disposition: form-data; name="file2"; filename="photo.jpg" 
Content-Type: image/jpeg
<двоичные данные файла photo.jpg>

--myBoundary--

--myBoundary обычно генерируется случайным образом из букв и цифр, чтобы исключить коллизии с данными в запросе.

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

Заключение

В процессе рассмотрения возможностей объекта FormData мы затронули множество важных концепций, связанных с отправкой данных в веб-приложениях.

Основные полученные знания:

  • FormData предоставляет удобный API для сбора и отправки данных форм, включая файлы
  • С помощью FormData можно легко организовать асинхронную отправку данных на сервер
  • Поддерживается добавление как файлов, так и дополнительных текстовых полей
  • Данные кодируются в формате multipart/form-data, позволяющем передавать файлы
  • Возможна гибкая настройка и динамическое изменение данных перед отправкой
  • Полученные данные легко обрабатываются на сервере
  • Реализуется инкапсуляция и надёжная передача данных

Также мы узнали про особенности работы с файлами в JavaScript и рассмотрели альтернативные способы отправки данных.

Формат FormData является рекомендованным и удобным решением в большинстве случаев, когда необходима асинхронная передача файлов или данных форм на сервер.

Написать комментарий