Когда я отправляю простую форму вроде этого с прикрепленным файлом:
<form enctype="multipart/form-data" action="http://localhost:3000/upload?upload_progress_id=12344" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="100000" />
Choose a file to upload: <input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>
Как это отправить файл внутри? Файл отправляется как часть тела HTTP как данные? В заголовках этого запроса я не вижу ничего, связанного с именем файла.
Я просто хотел бы знать внутреннюю работу HTTP при отправке файла.
http
file-upload
0xSina
источник
источник
MAX_FILE_SIZE
в PHP - какой смысл» на stackoverflow.com/q/1381364/632951Ответы:
Давайте посмотрим, что происходит, когда вы выбираете файл и отправляете форму (для краткости я обрезал заголовки):
ПРИМЕЧАНИЕ. Каждой граничной строке должен предшествовать дополнительный символ
--
, как в конце последней граничной строки. Пример выше уже включает это, но это может быть легко пропустить. Смотрите комментарий @Andreas ниже.Вместо URL, кодирующего параметры формы, параметры формы (включая данные файла) отправляются в виде разделов в многочастном документе в теле запроса.
В приведенном выше примере вы можете увидеть входные данные
MAX_FILE_SIZE
со значением, заданным в форме, а также раздел, содержащий данные файла. Имя файла является частьюContent-Disposition
заголовка.Полная информация здесь .
источник
Формат называется
multipart/form-data
, как спрашивается в: Что означает enctype = 'multipart / form-data'?Я собираюсь:
HTML5 ссылки
Есть три возможности для
enctype
:x-www-urlencoded
multipart/form-data
(спецификация указывает на RFC2388 )text-plain
, Это «ненадежно интерпретируется компьютером», поэтому никогда не должно использоваться в производстве, и мы не будем вдаваться в подробности.Как генерировать примеры
Как только вы видите пример каждого метода, становится очевидным, как они работают, и когда вы должны использовать каждый из них.
Вы можете привести примеры, используя:
nc -l
или сервер ECHO: тестовый сервер HTTP, принимающий запросы GET / POSTСохраните форму в минимальный
.html
файл:Мы устанавливаем текстовое значение по умолчанию
aωb
, что означает,aωb
потому чтоω
естьU+03C9
, которые являются байтами61 CF 89 62
в UTF-8.Создайте файлы для загрузки:
Запустите наш маленький эхо-сервер:
Откройте HTML в вашем браузере, выберите файлы, нажмите «Отправить» и проверьте терминал.
nc
печатает полученный запросПроверено на: Ubuntu 14.04.3,
nc
BSD 1.105, Firefox 40.многочастному / форм-данных,
Firefox отправил:
Для двоичного файла и текстового поля байты
61 CF 89 62
(aωb
в UTF-8) отправляются буквально. Вы можете проверить это с помощьюnc -l localhost 8000 | hd
, который говорит, что байты:были отправлены (
61
== 'a' и62
== 'b').Поэтому ясно, что:
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
устанавливает тип содержимогоmultipart/form-data
и говорит, что поля разделены заданнойboundary
строкой.Но обратите внимание, что:
имеет на два меньше черт,
--
чем фактический барьерЭто потому, что стандарт требует, чтобы граница начиналась с двух штрихов
--
. Похоже, что другие черты - это то, как Firefox решил реализовать произвольную границу. RFC 7578 четко упоминает, что эти две лидирующие черты--
необходимы:каждое поле получает некоторые вложенные заголовки перед своими данными:
Content-Disposition: form-data;
, полеname
, темfilename
, за которым следуют данные.Сервер читает данные до следующей граничной строки. Браузер должен выбрать границу, которая не будет отображаться ни в одном из полей, поэтому эта граница может варьироваться между запросами.
Поскольку у нас есть уникальная граница, кодирование данных не требуется: двоичные данные отправляются как есть.
ТОДО: каков оптимальный размер границы (
log(N)
бьюсь об заклад) и название / время выполнения алгоритма, который его находит? На вопрос: /cs/39687/find-the-shortest-sequence-that-is-not-a-sub-sequence-of-a-set-of-sequenceContent-Type
определяется автоматически браузером.Как именно это определяется, было задано по адресу: Как браузер определяет тип mime загруженного файла?
применение / х-WWW-форм-urlencoded
Теперь измените
enctype
кapplication/x-www-form-urlencoded
, перезагрузите браузер и повторите.Firefox отправил:
Ясно, что данные файла не были отправлены, только базовые имена. Так что это не может быть использовано для файлов.
Что касается текстового поля, мы видим, что обычные печатаемые символы, такие как
a
иb
были отправлены в один байт, а непечатные символы, такие как0xCF
и0x89
занимают 3 байта каждый%CF%89
:!сравнение
Загрузки файлов часто содержат много непечатных символов (например, изображений), в то время как текстовые формы почти никогда не делают.
Из примеров мы видели, что:
multipart/form-data
: добавляет к сообщению несколько байтов служебных данных границы и должен потратить некоторое время на его вычисление, но отправляет каждый байт по одному байту.application/x-www-form-urlencoded
: имеет одну байтовую границу для каждого поля (&
), но добавляет линейный коэффициент издержек в 3 раза для каждого непечатаемого символа.Поэтому, даже если бы мы могли отправлять файлы с помощью
application/x-www-form-urlencoded
, мы бы этого не хотели, потому что это так неэффективно.Но для печатных символов, найденных в текстовых полях, это не имеет значения и создает меньше накладных расходов, поэтому мы просто используем их.
источник
Content-Disposition
иContent-Type
атрибутов , но как справиться с «содержанием»?Отправить файл как двоичное содержимое (загрузить без формы или FormData)
В приведенных ответах / примерах файл (скорее всего) загружен с HTML-формой или с использованием API-интерфейса FormData . Файл является только частью данных, отправляемых в запросе, отсюда и
multipart/form-data
Content-Type
заголовок.Если вы хотите отправить файл в качестве единственного содержимого, вы можете напрямую добавить его в качестве тела запроса и установить в
Content-Type
заголовке тип MIME отправляемого файла. Имя файла можно добавить вContent-Disposition
шапку. Вы можете загрузить как это:Если вы не (не хотите) использовать формы и заинтересованы только в загрузке одного файла, это самый простой способ включить ваш файл в запрос.
источник
Content-Type
заголовок.У меня есть этот пример кода Java:
и у меня есть этот файл test.html:
и, наконец, файл, который я буду использовать для тестирования с именем a.dat, имеет следующее содержимое:
если вы интерпретируете байты выше как символы ASCII или UTF-8, они фактически будут представлять:
Итак, давайте запустим наш Java-код, откроем test.html в нашем любимом браузере, загрузим
a.dat
и отправим форму и посмотрим, что получит наш сервер:Ну, я не удивлен, увидев символы 9ie, потому что мы сказали Java печатать их, считая их символами UTF-8. Вы также можете прочитать их как необработанные байты.
на самом деле последний HTTP-заголовок здесь. После этого идет HTTP Body, где на самом деле видны мета и содержимое загруженного нами файла.
источник
http://www.tutorialspoint.com/http/http_messages.htm
источник