Что означает enctype = 'multipart / form-data'?

1114

Что означает enctype='multipart/form-data' в форме HTML и когда мы должны его использовать?

Теги:
http-headers
multipartform-data

9 ответов

1247
Лучший ответ

Когда вы делаете запрос POST, вы должны кодировать данные, которые каким-то образом формируют тело запроса.

HTML-формы предоставляют три метода кодирования.

  • application/x-www-form-urlencoded (по умолчанию)
  • multipart/form-data
  • text/plain

Работы по добавлению application/json выполнялись, но это было прекращено.

(Другие кодировки возможны с HTTP-запросами, сгенерированными с использованием других средств, кроме отправки HTML-форм.)

Специфика форматов не имеет значения для большинства разработчиков. Важными моментами являются:

  • Никогда не используйте text/plain.

Когда вы пишете код на стороне клиента:

  • используйте multipart/form-data когда ваша форма содержит какие-либо элементы <input type="file">
  • в противном случае вы можете использовать multipart/form-data или application/x-www-form-urlencoded но application/x-www-form-urlencoded будет более эффективным

Когда вы пишете код на стороне сервера:

  • Используйте заранее написанную библиотеку обработки форм

Большинство (например, Perl CGI->param или тот, который представлен в PHP $_POST superglobal) позаботятся о различиях за вас. Не пытайтесь анализировать необработанные данные, полученные сервером.

Иногда вы найдете библиотеку, которая не может обрабатывать оба формата. Наиболее популярной библиотекой Node.js для обработки данных форм является body-parser, который не может обрабатывать многокомпонентные запросы (но имеет документацию, которая рекомендует некоторые альтернативы, которые могут).


Если вы пишете (или отлаживаете) библиотеку для анализа или генерации необработанных данных, вам нужно начать беспокоиться о формате. Вы также можете узнать об этом ради интереса.

application/x-www-form-urlencoded более или менее совпадает со строкой запроса в конце URL.

multipart/form-data значительно сложнее, но позволяет включать в данные целые файлы. Пример результата можно найти в спецификации HTML 4.

text/plain введен в HTML 5 и полезен только для отладки - из спецификации: они не могут быть надежно интерпретированы компьютером - и я бы сказал, что другие объединены с инструментами (например, вкладка Net в инструментах разработчика большинства браузеров) ) лучше для этого).

  • 5
    @Quentin Извините, какие будут возможные проблемы, если мы будем использовать multipart для всех форм? с и без файлов.
  • 9
    Это не имеет смысла для форм GET, и это увеличивает размер файла запросов.
Показать ещё 13 комментариев
345

когда мы должны использовать это

Ответ Квентина верен: используйте multipart/form-data если форма содержит файл для загрузки, и application/x-www-form-urlencoded противном случае, что является значением по умолчанию, если вы опускаете enctype.

Я собираюсь:

  • добавить еще несколько ссылок HTML5
  • объясните, почему он прав с помощью примера

HTML5 ссылки

Есть три возможности для enctype:

  • x-www-urlencoded
  • multipart/form-data (спецификация указывает на RFC7578)
  • text-plain Это "ненадежно интерпретируется компьютером", поэтому никогда не должно использоваться в производстве, и мы не будем вдаваться в подробности.

Как генерировать примеры

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

Вы можете привести примеры, используя:

Сохраните форму в минимальный файл .html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8"/>
  <title>upload</title>
</head>
<body>
<form action="http://localhost:8000" method="post" enctype="multipart/form-data">
  <p><input type="text" name="text1" value="text default">
  <p><input type="text" name="text2" value="a&#x03C9;b">
  <p><input type="file" name="file1">
  <p><input type="file" name="file2">
  <p><input type="file" name="file3">
  <p><button type="submit">Submit</button>
</form>
</body>
</html>

Мы устанавливаем текстовое значение по умолчанию a&#x03C9;b, что означает aωb потому что ω равно U+03C9, которые являются байтами 61 CF 89 62 в UTF-8.

Создайте файлы для загрузки:

echo 'Content of a.txt.' > a.txt

echo '<!DOCTYPE html><title>Content of a.html.</title>' > a.html

# Binary file containing 4 bytes: 'a', 1, 2 and 'b'.
printf 'a\xCF\x89b' > binary

Запустите наш маленький эхо-сервер:

while true; do printf '' | nc -l 8000 localhost; done

Откройте HTML в вашем браузере, выберите файлы, нажмите "Отправить" и проверьте терминал.

nc печатает полученный запрос.

Проверено на: Ubuntu 14.04.3, nc BSD 1.105, Firefox 40.

многочастному/форм-данных,

Firefox отправил:

POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
Content-Length: 834

-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text1"

text default
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text2"

aωb
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file1"; filename="a.txt"
Content-Type: text/plain

Content of a.txt.

-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file2"; filename="a.html"
Content-Type: text/html

<!DOCTYPE html><title>Content of a.html.</title>

-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file3"; filename="binary"
Content-Type: application/octet-stream

aωb
-----------------------------735323031399963166993862150--

Для двоичного файла и текстового поля байты 61 CF 89 62 (aωb в UTF-8) отправляются буквально. Вы можете проверить это с помощью nc -l localhost 8000 | hd nc -l localhost 8000 | hd, который говорит, что байты:

61 CF 89 62

были отправлены (61 == 'a' и 62 == 'b').

Поэтому ясно, что:

  • Content-Type: multipart/form-data; boundary=---------------------------9051914041544843365972754266 Content-Type: multipart/form-data; boundary=---------------------------9051914041544843365972754266 устанавливает тип содержимого multipart/form-data и говорит, что поля разделены заданной boundary строкой.

  • каждое поле получает несколько подзаголовков перед своими данными: Content-Disposition: form-data; , name поля, name filename, а затем данные.

    Сервер читает данные до следующей граничной строки. Браузер должен выбрать границу, которая не будет отображаться ни в одном из полей, поэтому эта граница может варьироваться между запросами.

    Поскольку у нас есть уникальная граница, кодирование данных не требуется: двоичные данные отправляются как есть.

    TODO: каков оптимальный размер границы (log(N) я ставлю), и название/время работы алгоритма, который его находит? На вопрос: https://cs.stackexchange.com/questions/39687/find-the-shortest-sequence-that-is-not-a-sub-sequence-of-a-set-of-sequence

  • Content-Type автоматически определяется браузером.

    Как именно это определяется, было задано по адресу: Как браузер определяет тип mime загруженного файла?

применение/х-WWW-форм-urlencoded

Теперь измените enctype на application/x-www-form-urlencoded, перезагрузите браузер и повторите отправку.

Firefox отправил:

POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: application/x-www-form-urlencoded
Content-Length: 51

text1=text+default&text2=a%CF%89b&file1=a.txt&file2=a.html&file3=binary

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

Что касается текстового поля, мы видим, что обычные печатаемые символы, такие как a и b отправлялись одним байтом, в то время как непечатаемые символы, такие как 0xCF и 0x89 занимали 3 байта каждый: %CF%89 !

сравнение

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

Из примеров мы видели, что:

  • multipart/form-data: добавляет к сообщению несколько байтов служебных данных границы и должен потратить некоторое время на его вычисление, но отправляет каждый байт одним байтом.

  • application/x-www-form-urlencoded: имеет одну байтовую границу для каждого поля (&), но добавляет линейный коэффициент издержек 3x для каждого непечатаемого символа.

Поэтому, даже если бы мы могли отправлять файлы с application/x-www-form-urlencoded, мы бы этого не хотели, потому что это неэффективно.

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

  • 0
    Отличный пост. Вопрос: Почему у нас есть 3 байта для каждого непечатаемого символа? Например, для юникода U + 03C9 у нас есть% CF% 89: это два дополнительных байта для двух «%». Правильно ли мое понимание?
  • 2
    @ Khanna111 %CF имеет длину 3 байта: % , C и F :-) История создания его удобочитаемым для человека.
Показать ещё 11 комментариев
76

enctype='multipart/form-data - это тип кодирования, который позволяет отправлять файлы через POST. Совершенно просто, без этой кодировки файлы не могут быть отправлены через POST.

Если вы хотите разрешить пользователю загружать файл через форму, вы должны использовать этот enctype.

  • 0
    Итак ... если файл не является двоичным файлом, то можем ли мы работать без этого?
  • 0
    Из того, что я понимаю, вы можете использовать multipart/form-data для отправки недвоичных файлов, но это неэффективно. Я считаю, что использование application/x-www-form-urlencoded является правильным способом отправки недвоичных данных, но кому-то, имеющему больше опыта работы с недвоичными файлами, возможно, придется поправить меня.
Показать ещё 3 комментария
68

При отправке формы вы пытаетесь сказать, что ваш браузер отправил через протокол HTTP сообщение в сети, должным образом заключенное в структуру сообщения протокола TCP/IP. При отправке данных вы можете использовать методы POST или GET HTTP.

  • POST сообщает вашему браузеру, что нужно создать HTTP-сообщение и поместить все содержимое в тело сообщения (очень полезный способ сделать что-то более безопасное и гибкое).
  • GET отправит данные формы в строке запроса. Это имеет некоторые ограничения относительно представления данных и длины.

Заявление о том, как отправить вашу форму на сервер

Атрибут enctype имеет смысл только при использовании метода POST. Если указано, он указывает браузеру отправлять форму, кодируя ее содержимое определенным образом. От MDN - Форма энктипа:

Если значение атрибута метода - post, enctype - это тип содержимого MIME, который используется для отправки формы на сервер.

  • application/x-www-form-urlencoded: это значение по умолчанию. Когда форма отправляется, все имена и значения собираются, и в последней строке выполняется кодировка URL.
  • multipart/form-data: символы НЕ кодируются. Это важно, когда форма имеет элемент управления загрузкой файлов. Вы хотите отправить двоичный файл, и это гарантирует, что поток битов не будет изменен.
  • text/plain: пробелы преобразуются, но кодирование больше не выполняется.

Безопасность

При отправке форм могут возникнуть некоторые проблемы с безопасностью, как указано в RFC 7578, Раздел 7: Составные данные форм - Соображения безопасности:

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

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

Это важно при интерпретации имени файла Content-
Поле заголовка расположения, чтобы случайно не перезаписать файлы в
файловое пространство получателя.

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

  • 0
    Материал о безопасности после самого последнего редактирования не имеет отношения к вопросу о том, что enctype . Я знаю, что это буквально из RFC multipart/form-data , но, тем не менее, это произвольный дамп соображений безопасности при отправке форм, которые полностью ортогональны тому, отправляются ли данные как application/x-www-form-urlencoded или multipart/form-data ,
29

enctype='multipart/form-data' означает, что никакие символы не будут закодированы. поэтому этот тип используется при загрузке файлов на сервер.
Таким образом, multipart/form-data используется, когда форма требует, чтобы бинарные данные, такие как содержимое файла, загружались

8

Установите атрибут метода POST, потому что содержимое файла не может быть помещено в параметр URL с помощью формы.

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

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

Атрибут enctype указывает, как данные формы должны быть закодированы при отправке на сервер.

Атрибут enctype можно использовать только если method = "post".

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

Из W3Schools

  • 0
    Эта цитата даже не упоминает multipart/form-data . Это также довольно неясно; что вообще означает предложение «Никакие символы не закодированы»? -1.
0

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

0
  • Атрибут enctype (ENC ode TYPE) указывает, как данные формы должны быть закодированы при отправке их на сервер.
  • multipart/form-data - это одно из значений атрибута enctype, которое используется в элементе формы, в который загружается файл. multi-part означает, что данные формы разделяются на несколько частей и отправляются на сервер.
  • 4
    Я считаю, что enctype не означает тип шифрования. На этом уровне шифрование не используется. Я предполагаю, что это либо тип кодировки, либо закрытый тип. Но, конечно, это не тип шифрования.
  • 0
    Ваш последний пункт о <head> и <body> здесь не имеет значения и сбивает с толку.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню