Stop 10 · API IntegrationTopics · 16/16

Multipart Form

Part of the Frontend Developer Roadmap

In short

JSON can't carry a photo by itself. When you send files along with normal fields, the browser packs them as multipart/form-data, and FormData does the packing for you.

The `multipart/form-data` encoding used to send files alongside regular form fields in a single HTTP request.

The jaadu packs rotis, sabzi and dal into separate compartments of a steel tiffin.

Think of it like this

A dabba with compartments

A steel tiffin has separate sections: roti in one, sabzi in another, dal in the third. Each stays separate but travels together. Multipart is that tiffin: name, email and photo each get their own section in one request.

Watch it happen

One request, many parts

Browser
Server
append title, photo

1/5FormData collects a text part and a file part, like filling tiffin compartments.

The big ideas

What you need to know

Each field is a part

The body is split into parts separated by a boundary string. Each part has its own name and content.

FormData builds it

Call formData.append("name", value) for text and formData.append("photo", file) for files.

Don't set Content-Type

Let the browser set it. It adds the boundary value, and the server needs that to split the parts.

Progress needs XHR or Axios

fetch has no simple upload progress event. Axios's onUploadProgress or XMLHttpRequest gives you a percentage.

See it in code

Walk through the code

ts
1const form = new FormData();2form.append("title", "My hostel room");3form.append("photo", file); // a File from <input type="file">4 5await axios.post("/api/uploads", form, {6  onUploadProgress: (e) => {7    if (e.total) setProgress(Math.round((e.loaded / e.total) * 100));8  },9});10 11// With fetch: same FormData, and NO Content-Type header12await fetch("/api/uploads", { method: "POST", body: form });

1/3Each append adds a named part. Text and files can sit side by side.

Pass the FormData as the body and let the browser write the multipart header. Axios gives you upload progress for a progress bar.

Save yourself the pain

Common mistakes

Oops

Setting headers: { "Content-Type": "multipart/form-data" } by hand.

Do this instead

Leave it out. The browser adds the header with the boundary, which the server needs.

Oops

Using JSON.stringify on a FormData object.

Do this instead

Send the FormData directly as the body. Stringifying turns it into an empty object.

Your mission

Upload with a progress bar

~35 min

Quick check

Why should you not set the Content-Type header yourself when sending FormData?

Go deeper

  1. 1Build a form combining text fields and a file upload in one `FormData` submission.
  2. 2Inspect the raw request body's boundary-separated structure in DevTools.
  3. 3Learn why multipart encoding is necessary instead of plain JSON for file uploads.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge