Welcome To Golang By Example

HTTP- Understanding multipart/form-data content-type

In HTTP context, the multipart/form-data content-type is used for submitting HTML form. In the case of multipart/form-data, as the name suggests the body consists of different parts separated by a delimiter or boundary where each part is described by its own headers. The delimiter or boundary is also sent as part of the header only.

When you sending an HTML form through a browser in an HTTP call, the data contents can be sent in as request body below two formats.

For most of the cases, application/x-www-form-urlencoded can be used. application/x-www-form-urlencoded is not much efficient for

For example, let’s say that the below data needs to be sent.

Then application/x-www-form-urlencoded can be used to send the above data. But let’s say that you also need to send the profile photo of the user in the request as well. So the data is now as below

In the above case, it will not be efficient to use application/x-www-form-urlencoded content-type. multipart/form-data should be used in this case. So for sending simple form data use application/x-www-form-urlencoded but if the form-data also needs to send binary data then use multipart/form-data

Why is that?.  We will answer this question once we have understood the format of application/x-www-form-urlencoded and multipart/form-data. 

application/x-www-form-urlencoded encodes each non-ASCII byte to 3 bytes. Basically applcation/x-www-form-urlencoded content-type request body is like a giant query string. Similar to the query string in a URI it is a key-value pair having the below format

key1=value1&key2=value21&key2=value22&key3=value3

While sending application/x-www-form-urlencoded, all the non-alphanumeric characters are URL encoded. All the non-alphanumeric character(reserved only) will be URL encoded in the below format

%WW

Where WW is the ASCII code of the alphanumeric character represented in hexadecimal format.  As all the non-alphanumeric characters in the binary data are URL encoded where 1 byte is converted to 3 bytes. So size is increased three folds.  So if you sending a file or image which is a lot of binary data then your payload will be very big i.e almost thrice the size of the actual payload. Hence it is inefficient for sending large binary files or large NON-ASCII data.

To fully understand the format of application/x-www-form-urlencoded  please refer to this link

Now let’s understand the format of multipart/form-data.

As we mentioned before as well multipart/form-data has different parts separated by a delimiter or a boundary. Each part is described by its own header. The format of multipart/form-data is as below

--
Content-Disposition: form-data; name=""
Content-Type: 

[DATA]
--
Content-Disposition: form-data; name=""; filename=""
Content-Type: 
[DATA]
----

As you can notice above that format starts with a delimiter or boundary and ends with a delimiter or boundary. The above format is divided into two parts. Also,

Content-Disposition header for each part will be form-data. If you are sending binary data then 

Let’s say we are sending the below data as part of multipart/form-data request

And let’s say the delimiter or boundary is

xyz

Then the format will be as below

--xyz
Content-Disposition: form-data; name="name"
Content-Type: text/plain

John
--xyz
Content-Disposition: form-data; name="age"
Content-Type: text/plain

23
--xyz
Content-Disposition: form-data; name="photo"; filename="photo.jpeg"
Content-Type: image/jpeg

[JPEG DATA]
--xyz--

As multipart/form-data will send the binary data as it is, that is why it is used for sending files and large binary data. Now the question is. Why not use form-data all the time then?

The reason is that for small data the additional requirement of boundary string and headers will outweigh any optimizations. For example, let’s say we have the below data to be sent

Then while using application/x-www-form-urlencoded the data will be sent as

name=John&age=23

But while sending multipart/form-data the data will be sent as below which is almost 10 times the data that is sent in application/x-www-form-urlencoded

--xyz
Content-Disposition: form-data; name="name"
Content-Type: text/plain

John
--xyz
Content-Disposition: form-data; name="age"
Content-Type: text/plain

23
--xyz--

Conclusion

This is all about multipart/form-data. Hope you have liked this article. Please share feedback in the comments