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


Ответы:


1570

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

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

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

Работа над добавлением была сделана application/json, но это было заброшено.

(Другие кодировки возможны с HTTP-запросами, сгенерированными с использованием других средств, кроме отправки HTML-форм. JSON - это распространенный формат для использования с веб-службами, а некоторые все еще используют SOAP.)

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

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

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

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

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

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

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

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


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

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

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

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


5
@Quentin Извините, какие будут возможные проблемы, если мы будем использовать multipart для всех форм? с и без файлов.
Вебинан

12
Это не имеет смысла для форм GET, и это делает размер файла запросов больше.
Квентин

@Quentin по умолчанию данные из нескольких частей отправляются в виде потока?
Growler

Enc in enctype означает что-то?
Филипп Рего

1
«HTML-формы предоставляют три метода одирования ENC »
Квентин,

449

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

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

Я собираюсь:

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

HTML5 ссылки

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

  • application/x-www-form-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, ncBSD 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, который говорит, что байты:

61 CF 89 62

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

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

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

    Но обратите внимание, что:

    boundary=---------------------------735323031399963166993862150

    имеет на два меньше черт, --чем фактический барьер

    -----------------------------735323031399963166993862150

    Это потому, что стандарт требует, чтобы граница начиналась с двух штрихов --. Похоже, что другие черты - это то, как Firefox решил реализовать произвольную границу. RFC 7578 четко упоминает, что эти две лидирующие черты --необходимы:

    4.1. «Граничный» параметр multipart / form-data

    Как и в случае других составных типов, части разделяются граничным разделителем, созданным с использованием CRLF, "-" и значения параметра "border".

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

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

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

    ТОДО: каков оптимальный размер границы ( log(N)бьюсь об заклад) и название / время выполнения алгоритма, который его находит? На вопрос: /cs/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: имеет одну байтовую границу для каждого поля ( &), но добавляет линейный коэффициент издержек в 3 раза для каждого непечатаемого символа.

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

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


3
@ Khanna111 %CF3 байта длиной: %, Cи F:-) История делает его читаемым человеком.
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

6
На OS X, ncне будут принимать как -lи те -pаргументы одновременно. Но это работает для меня while true; do printf '' | nc -l 8000; done.
PhilipS

4
Небольшой, но важный момент, который не упоминается, состоит в том, что граница, указанная в, Content-Typeимеет на два дефиса ( --) меньше, то есть при фактическом использовании границы в теле сообщения вы должны использовать префикс --. Кроме того, к последней границе должен быть добавлен суффикс --, но это достаточно легко заметить. См. Stackoverflow.com/questions/3508252/…
Бернард

1
Насколько я могу судить, смысл помещать ЛЮБЫЕ ЧЕРТЫ ВСЕ в границу состоит в том, чтобы сделать невозможным проверку синтаксиса запроса на глаз. Пожалуйста, не используйте их в своих жетонах границы.
Деви Морган

1
@DewiMorgan Вы совершенно правы. Я отредактировал пост и удалил штрихи из граничной строки.
Макс

91

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

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


Итак ... если файл не является двоичным файлом, то можем ли мы работать без этого?
Югаль Джиндл

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

11
Основным преимуществом использования multipart/form-dataдля отправки файла является то, что он будет работать автоматически как во внешнем, так и во внутреннем интерфейсе. Вам не нужно делать никакой специальной обработки. Все файлы являются двоичными, даже если они должны содержать только текст. application/x-www-form-urlencodedэто стандартный способ отправить форму без вложенных файлов. multipart/form-dataэто стандартный способ отправить форму с приложенным файлом (ами). (Существует также множество других кодировок, таких как application/jsonи application/json-patch+json, которые являются общими для связи между сервером и клиентом.)
Даниэль Луна

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

3
В дополнение к комментарию @ Prospero выше: вы можете отправлять файлы через POST без использования multipart/form-data. То, что вы не можете сделать, это сделать, используя обычную отправку HTML-формы, без JavaScript. Настройка формы для использования multipart/form-data- единственный механизм, который предоставляет HTML, чтобы позволить вам POST-файлы без использования JavaScript. Я чувствую, что это не достаточно ясно в ответе, и что наивный читатель может подумать, что невозможность отправки файлов multipart/form-data- это ограничение HTTP ; это не тот случай.
Марк Амери

81

При отправке формы вы указываете браузеру отправлять по протоколу HTTP сообщение в сети, надлежащим образом заключенное в структуру сообщения протокола TCP / IP. На странице HTML есть способ отправки данных на сервер: с помощью <form>s.

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

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

Указание, как отправить вашу форму на сервер

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

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

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

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

При отправке форм могут возникать некоторые проблемы безопасности, как указано в Разделе 7 RFC 7578: Данные из нескольких частей - Вопросы безопасности :

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

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

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

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


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

38

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


8

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

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


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

1
  • ENCTYPE ( ЭНК ода ТИП ) атрибут определяет , как форма-данные должны быть закодированы при подаче его на сервер.
  • multipart / form-data - это одно из значений атрибута enctype, которое используется в элементе формы, в который загружается файл. multi-part означает, что данные формы разделяются на несколько частей и отправляются на сервер.

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

1
Ваш последний пункт здесь о <head>и не <body>имеет значения и сбивает с толку.
Марк Амери

0

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


-3

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

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

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

Из W3Schools


2
Эта цитата даже не упоминается multipart/form-data. Это также довольно неясно; что вообще означает предложение «Никакие символы не закодированы»? -1.
Марк Амери
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.