Как это отправить файл внутри?
Формат называется multipart/form-data
, как спрашивается в: Что означает enctype = 'multipart / form-data'?
Я собираюсь:
- добавить еще несколько ссылок 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.
многочастному / форм-данных,
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
, мы бы этого не хотели, потому что это так неэффективно.
Но для печатных символов, найденных в текстовых полях, это не имеет значения и создает меньше накладных расходов, поэтому мы просто используем их.