Content of a.html.

How does HTTP file upload work?

How does it send files internally? Is the file sent as part of the data as an HTTP body? In the title of this request, you do not see anything related to the filename.

I just want to know how HTTP works internally when sending files.

#1 building

How does it send files internally?

HTML5 reference

  • x-www-urlencoded
  • multipart/form-data (specification direction RFC2388 )
  • text-plain . This can’t be reliably explained by a computer, so never use it in production, and we won’t study it in depth.

How to generate an example

Once you see examples of each method, it’s clear how they work and when to use each method.

You can generate an example using the following example:

Save the form to the smallest. html file:

We set the default text value to a & (x03c9; b), which means a ω B because ω is U+03C9, which is byte 61 CF 89 62 in UTF-8.

To create a file to upload:

echo 'Content of a.txt.' > a.txt echo '' > 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 

Open HTML on the browser, select the file, then click Submit and check the terminal.

nc prints the received request.

Tested in: Ubuntu 14.04.3, nc BSD 1.105, Firefox 40.

Multipart / form data

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  -----------------------------735323031399963166993862150 Content-Disposition: form-data; name="file3"; filename="binary" Content-Type: application/octet-stream aωb -----------------------------735323031399963166993862150-- 

For binary and text fields, bytes 61 CF 89 62 (a ω b in UTF-8) are sent literally. You can use nc -l localhost 8000 | hd nc -l localhost 8000 | hd to represent bytes:

  • Content type: multipart / form data; boundary = ———————— 9051914041544843365972754266 content type: multipart / form data; boundary = ———————— 9051914041544843365972754266 set the content type to multipart / form data and the character segment is separated by the given boundary string.
  • Each field has some subheadings before its data: content disposition: form data;, field name, filename, and data. The server reads the data until the next boundary string. The browser must select a boundary that does not appear in any field, so that’s why the boundaries between requests may be different. Because we have a unique boundary, there is no need to code the data: send binary data as is. TODO: what is the optimal boundary size (I bet log(N)), and what is the name / running time of the algorithm to find it? Ask at: https : //cs.stackexchange.com/questions/39687/find-the-shortest-sequence-that-is-not-a-sub-sequence-of-a-set-of-sequences
  • The content type is automatically determined by the browser. Ask at How to determine it: how does the browser determine the mime type of the uploaded file?

Application / x-www-form-urlencoded

Now change the enctype to application/x-www-form-urlencoded, reload the browser, and resubmit.

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 

Obviously, no file data was sent, just the base name. Therefore, this cannot be used for files.

For text fields, we see that generally printable characters (such as a and b) are sent in one byte, while non printable 0xCF (such as 0xCF and 0x89) each occupies three bytes:% CF%89!

Comparison mode

File uploads usually contain many non printable characters (such as images), while text forms are almost never available.

From the example, we can see:

  • Multipart / form data: adds some boundary overhead bytes to the message, and it must take some time to calculate it, but each byte is sent in one byte.
  • application/x-www-form-urlencoded: each field (&) has a single byte boundary, but increases the linear overhead factor by three times for each non printable character.

So even if we can send with application/x-www-form-urlencoded, we don’t apply / x-www-form-urlencoded because it’s inefficient.

But for printable characters found in text fields, it doesn’t matter, and it costs less, so we only use it.

#2 building

Send file as binary content (upload without form or FormData)

In the given answer / example, the file (most likely) is using an HTML form or using the FormData API Uploaded. This file is only part of the data sent in the request, so it is the multipart / form data content type header.

If you want to send a file as unique content, you can add it directly as the request body and set the content type header to the MIME type of the file you want to send. You can add a filename to the content disposition header. You can upload as follows:

var xmlHttpRequest = new XMLHttpRequest(); var file = . file handle. var fileName = . file name. var target = . target. var mimeType = . mime type. xmlHttpRequest.open('POST', target, true); xmlHttpRequest.setRequestHeader('Content-Type', mimeType); xmlHttpRequest.setRequestHeader('Content-Disposition', 'attachment; filename="' + fileName + '"'); xmlHttpRequest.send(file);

If you don’t (don’t want to) use the form and are only interested in uploading a single file, this is the easiest way to include the file in the request.

#3 building

I have the following sample Java code:

import java.io.*; import java.net.*; import java.nio.charset.StandardCharsets; public class TestClass < public static void main(String[] args) throws IOException < final ServerSocket socket = new ServerSocket(8081); final Socket accept = socket.accept(); final InputStream inputStream = accept.getInputStream(); final InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); char readChar; while ((readChar = (char) inputStreamReader.read()) != -1) < System.out.print(readChar); >inputStream.close(); accept.close(); System.exit(1); > > 

Finally, the file a.dat, which I will use for testing purposes, has the following:

If you interpret these bytes as ASCII or UTF-8 characters, they will actually represent:

Therefore, let’s run our Java code, open test.html in our favorite browser, upload a.dat and submit the form to see what our server has received:

POST / HTTP/1.1 Host: localhost:8081 Connection: keep-alive Content-Length: 196 Cache-Control: max-age=0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Origin: null Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.97 Safari/537.36 Content-Type: multipart/form-data; boundary=----WebKitFormBoundary06f6g54NVbSieT6y DNT: 1 Accept-Encoding: gzip, deflate Accept-Language: en,en-US;q=0.8,tr;q=0.6 Cookie: JSESSIONID=27D0A0637A0449CF65B3CB20F40048AF ------WebKitFormBoundary06f6g54NVbSieT6y Content-Disposition: form-data; name="file"; filename="a.dat" Content-Type: application/octet-stream 9ie ------WebKitFormBoundary06f6g54NVbSieT6y-- 

Well, I’m not surprised to see the characters 9ie, because we told Java to print them as UTF-8 characters. You can also choose to read them as raw bytes.

Cookie: JSESSIONID=27D0A0637A0449CF65B3CB20F40048AF 

It’s actually the last HTTP header here. After that is the HTTP body, where you can actually see the metadata and content of the file we uploaded.

#4 building

An HTTP message may have a data body that is sent after the header line. In the response, this is where the requested resource is returned to the client (the most common use of the message body), and if there is an error, it can also be interpreted text. In the request, the data entered by the user or the uploaded file is sent to the server.

#5 building

Let’s take a look at what happens when you select a file and submit a form (I’ve abridged the title for brevity):

POST /upload?upload_progress_id=12344 HTTP/1.1 Host: localhost:3000 Content-Length: 1325 Origin: http://localhost:3000 . other headers . Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryePkpFF7tjBAqx29L ------WebKitFormBoundaryePkpFF7tjBAqx29L Content-Disposition: form-data; name="MAX_FILE_SIZE" 100000 ------WebKitFormBoundaryePkpFF7tjBAqx29L Content-Disposition: form-data; name="uploadedfile"; filename="hello.o" Content-Type: application/x-object . contents of file goes here . ------WebKitFormBoundaryePkpFF7tjBAqx29L-- 

Form parameters (including file data) instead of URL encoding form parameters are sent as parts in multi part documents in the request body.

In the above example, you can see the input of max file size and the value of max file size in the form, as well as the part containing the file data. The filename is part of the content disposition header.

Posted on Mon, 20 Jan 2020 00:50:52 -0500 by ScoobyDooobyD00

Hot Tags

  • Java — 7906
  • Database — 3176
  • Python — 3103
  • Attribute — 2963
  • Programming — 2938
  • Javascript — 2788
  • Spring — 2575
  • xml — 2270
  • Android — 2243
  • Linux — 2204
  • JSON — 2150
  • less — 2137
  • network — 2115
  • github — 2063
  • MySQL — 1760
  • SQL — 1616
  • PHP — 1559
  • encoding — 1360
  • Mobile — 1172
  • Apache — 1137

Источник

Загрузка файлов

Для того чтобы можно было загружать на сервер один или несколько файлов, в форме применяется специальное поле. В браузерах Firefox, IE и Opera такой элемент отображается как текстовое поле, рядом с которым располагается кнопка с надписью «Обзор. » (рис. 1). В Safari и Chrome доступна только кнопка «Выберите файл» (рис. 2).

Вид поля для загрузки файла в Firefox

Рис. 1. Вид поля для загрузки файла в Firefox

Загрузка файлов в Chrome

Рис. 2. Загрузка файлов в Chrome

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

Синтаксис поля для отправки файла следующий.

Атрибуты перечислены в табл. 1.

Табл. 1. Атрибуты поля для отправки файла
Атрибут Описание
accept Устанавливает фильтр на типы файлов, которые вы можете отправить через поле загрузки файлов.
size Ширина текстового поля, которое определяется числом символов моноширинного шрифта.
multiple Позволяет выбирать и загружать сразу несколько файлов.
name Имя поля, используется для его идентификации обработчиком формы.

Прежде, чем использовать данное поле, в форме необходимо сделать следующее:

  1. задать метод отправки данных POST ( method=»post» );
  2. установить у атрибута enctype значение multipart/form-data .

Форма для загрузки файла продемонстрирована в примере 1.

Пример 1. Создание поля для отправки файла

Хотя можно установить ширину поля через атрибут size , в действительности ширина никак не влияет на результат работы формы. В браузерах Safari и Chrome этот атрибут вообще никакого воздействия не оказывает.

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

Если атрибут accept не указывать, тогда добавляются и загружаются файлы любого типа. Наличие accept позволяет ограничить выбор файла, что особенно важно, когда требуется загрузить только изображение или видео. В качестве значения выступает MIME-тип, несколько значений разделяются между собой запятой. Также можно использовать следующие ключевые слова:

  • audio/* — выбор музыкальных файлов любого типа;
  • image/* — графические файлы;
  • video/* — видеофайлы.

В табл. 2 показаны некоторые допустимые значения атрибута accept .

Табл. 2. Типы файлов

Значение Описание
image/jpeg Только файлы в формате JPEG.
image/jpeg,image/png Только файлы в формате JPEG и PNG.
image/* Любые графические файлы.
image/*,video/* Любые графические и видеофайлы.

Использование дополнительных атрибутов показано в примере 2.

Пример 2. Загрузка фотографий

       

Загрузите ваши фотографии на сервер

Не все браузеры поддерживают новые атрибуты. IE полностью игнорирует multiple и accept , Safari не поддерживает accept , а Firefox не работает с MIME-типом, только с ключевыми словами. Поэтому в примере выше специально для Firefox установлено значение image/*,image/jpeg . Также учтите странную ошибку в Опере, она не допускает пробелы после запятой внутри accept .

Результат примера показан на рис. 3. Обратите внимание, что из-за наличия multiple несколько изменился вид поля.

Загрузка файлов в Opera

Рис. 3. Загрузка файлов в Opera

Источник

Читайте также:  Scaling image in php
Оцените статью