когда мы должны его использовать
Правильный ответ Квентина: используйте multipart/form-data
, если форма содержит файл для загрузки, и application/x-www-form-urlencoded
в противном случае, что по умолчанию, если вы пропуститеenctype
.
Я собираюсь:
- добавить еще несколько ссылок на HTML5
- объяснить почему он прав с формойотправить пример
HTML5 ссылки
Существует три варианта для enctype
:
Как создавать примеры
Как только выПосмотрите пример каждого метода, становится очевидным, как они работают, и когда вы должны использовать каждый из них.
Вы можете создавать примеры, используя:
Сохранение формы в минимальном .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ω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ω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.
multipart / form-data
Отправленный 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=---------------------------9051914041544843365972754266
устанавливает тип содержимого на multipart/form-data
и говорит, что поля разделены заданной строкой boundary
.
каждое поле получает несколько подзаголовков перед своими данными: Content-Disposition: form-data;
, поле 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-sequences
Content-Type
автоматически определяется браузером.
Как точно определяется, был задан на: Как MIME-тип загруженногофайл определен браузером?
application / x-www-form-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
: имеет одну байтовую границу на поле (&
), но добавляет linear коэффициент издержек 3x для каждого непечатаемого символа.
Поэтому, даже если бы мы могли отправлять файлы с application/x-www-form-urlencoded
, мы бы этого не хотели, потому что это так неэффективно.
Но для печатаемых символов, найденных в текстовых полях, это не имеет значения и создает меньше накладных расходов, поэтому мы просто используем их.