When you are sending a file to the server, it is necessary to use an encoding that allows you to send binary data together with form data.
Normally a POST without files on the form has a body with the following format:
campo1=1234&campo2=Miguel&campo3=30
This format is identical to the format of the query-string in the URI.
Note that it would not be possible to send a binary file with this format unless it was converted to some text format, such as base-64. But this is not the case, since base-64 or any other text encoding would undoubtedly increase the size of the request.
For this there is a coding format that allows the sending of binary data: multipart/form-data
.
Coding multipart/form-data
This encoding allows you to transmit files in the same binary format to the server. It is defined in the HTTP 1.1 section 3.7.2 Multipart Types (rfc1867 ).
The encoding format consists of generating random tabs, and separating each field from the form with this tab.
See an example POST using this encoding: ( example of this site )
POST /diretorio/arquivo HTTP/1.0
Host: www.dominio.com.br
Content-type: multipart/form-data, boundary=AaB03x
Content-Length: 381
--AaB03x
content-disposition: form-data; name="campo1"
1234
--AaB03x
content-disposition: form-data; name="campo2"
Miguel
--AaB03x
content-disposition: form-data; name="arquivo1"; filename="minha-foto.jpg"
Content-Type: image/jpeg
Content-Transfer-Encoding: binary
ÿØÿà�JFIF��'�'��ÿî�Adobe�d����ÿá]Exif��MM�*����2�������b;�������vGF�������GI�����?������
--AaB03x--
Some rules of content formation:
Header Content-type
: should be multipart/form-data; boundary=$divisor-aleatorio
replacing the random divider with something really random and with almost 0 chance of repeating itself in the contents of the binary file or in any sent field.
>
Header Content-Length
: must have the size of the request, counting from the first divider (in the previous example is --AaB03x
), to the last character of the terminator ('' --AaB03x -)
For each field or file:
add divider
add division headers:
-
content-disposition: form-data
-
name="nome-do-campo-no-html"
- if it is a file:
-
filename="nome-do-arquivo-sendo-enviado"
: only if file
-
Content-Type: image/jpeg
: mime type of file
-
Content-Transfer-Encoding: binary
- skips a line, and then sends the data
- As soon as you finish, another divisor of the next field or terminator comes
add terminator
Submitting form
with multipart/form-data
In HTML, to indicate that you want to use the multipart/form-data
encoding, simply add the form
attribute to the enctype="multipart/form-data"
tag
Documentation of tag form
in MDN
According to the MDN documentation, this is required when using input
with type="file"
.