Understanding Multipart Content: What is it and how does it work?

What is Multipart Data?

When we send web requests we usually want to pass data between clients and servers. A lot of the time, we want to submit forms or multiple pieces of data in a single request.

That's what the multipart data type for.

You declare it in your request headers as the Content-Type to let the server know what type of data it is receiving. And in this case, it's receiving multiple pieces of data.

Next, we'll cover the basics on when to use it, how it works, and what it looks like in a real request.

Feel free to read more in the official W3C specifications too.


When Should I Use a Multipart Content-Type?

A lot of requests don't need to use the multipart Content-Type.

The application/x-www-form-urlencoded Content-Type is the default content type in forms and in my opinion is a lot simpler and easier to work with.

The data in this type of request is URL encoded, like /submit?name=testsuite&day=Tuesday.

The problem is, it's not efficient for sending lots of data or text with special characters. This is where content types like multipart/form-data steal the show and make it possible to pass more data in a more flexible way.

I would recommend these guidelines:

  • application/x-www-form-urlencoded is nice when requests are small with no special characters
  • Use multipart/form-data for larger requests, files, or when special characters are used

What is the Multipart Boundary?

The boundary is required with the multipart Content-Type.

It tells the receiver how to split the data it receives, since multiple pieces of data with potentially different types are being received together.

Generally, the frameworks and tools we use to send requests will handle adding the correct boundary to the request for us.


What Does a Multipart Request Look Like?

Here's an example from StackOverflow.

POST /cgi-bin/qtest HTTP/1.1
Host: aram
User-Agent: Mozilla/5.0 Gecko/2009042316 Firefox/3.0.10
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://aram/~martind/banner.htm
Content-Type: multipart/form-data; boundary=2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f
Content-Length: 514

--2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f
Content-Disposition: form-data; name="datafile1"; filename="r.gif"
Content-Type: image/gif

GIF87a.............,...........D..;
--2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f
Content-Disposition: form-data; name="datafile2"; filename="g.gif"
Content-Type: image/gif

GIF87a.............,...........D..;
--2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f
Content-Disposition: form-data; name="datafile3"; filename="b.gif"
Content-Type: image/gif

GIF87a.............,...........D..;
--2a8ae6ad-f4ad-4d9a-a92c-6d217011fe0f--

You can see the Content-Type is declared as multipart/form-data meaning there are multiple entities being passed in this request and each will define its own Content-Type.

Featured
Level up faster
Recommended Books
Check out my list.
One on Ones: 101
Leveraging Other People's Experience
Hey, I'm Nicholas Dill.

I share everything I know about web development and SEO.

My agency is also offering free site audits for a limited time. Take me up on it while you can!

FREE SEO AUDIT