Working with Multipart Form Data in Angular

Working with Multipart Form Data in Angular

Error submitting multipart/form-data

Assume you have an API that accepts 'multipart/form-data' and you have created an Angular service to POST some data to this API...

typescript
1@Injectable({ providedIn: 'root' })
2export class MemberService {
3	protected readonly URL = 'url to api endpoint';
4	constructor(protected http: HttpClient) { }
5	
6	post(name: string, age: number, alive: boolean) {
7	  const data = new FormData();
8	  data.append('name', name);
9	  data.append('age', age);
10	  data.append('alive', alive);
11
12	  const headers = new HttpHeaders()
13		  .set('content-type', 'multipart/form-data');
14		  
15	  return this.http.post(URL, data, { headers });
16	}
17}

What is wrong with the approach above?

hint #1 Have a look at the request headers

hint #2 Multipart forms need a boundary

Issue

By explicitly setting the content-type, you do not get the important boundary component of the header.

Solution

Let HttpClient do the work for you. First off, do not set the content-type. Instead, HttpClient will see that the payload (data) is FormData and will set the header appropriately (with the boundary component).

If you want to specify the content-type header yourself, have a look at the specification to learn more about how boundaries are required and how to set them.

Asides

Here are a couple of gotchas that have experienced over the years.

Headers vs HttpHeaders

I jump between Angular and plain JavaScript in my projects, and this gotcha has resulted in way too much wasted time on my part.

When I set headers for my fetch statement in JavaScript, it looks like this...

typescript
1const header = new Headers();
2header.append('x-api-code', '123');
3header.append('x-api-version', '3');
4header.append('x-api-ns', 'alpha');
5//check
6header.forEach((value, key) => {
7  console.log(key, value);
8});

This results in:

"x-api-code" "123"
"x-api-ns" "alpha"
"x-api-version" "3"

But I get nothing when I move to Angular and try similar code. There is nothing in the header.

typescript
1const header = new HttpHeaders();
2header.append('x-api-code', '123');
3header.append('x-api-version', '3');
4header.append('x-api-ns', 'alpha');
5//check
6header.keys().forEach((key) => {
7  const value = header.get(key);
8  console.log(key, value);
9});

I had to adjust the //check code because HttpHeaders does not have a .forEach() method. But, the fact remains - there is no output. Why?

Immutability! HttpHeaders are immutable. So you adjust your code to the following, and the headers will be back.

typescript
1const header = new HttpHeaders()
2  .append('x-api-code', '123')
3  .append('x-api-version', '3')
4  .append('x-api-ns', 'alpha');
5//check
6header.keys().forEach((key) => {
7  const value = header.get(key);
8  console.log(key, value);
9});

HttpHeaders .set vs .append

When you are working with headers, there are two methods of adding a header: .set() and .append().

Both will add a header key/value pair. The difference between the two is visible when there is already a header with the same key in the group.

  • .set() will override the existing value and replace it with the new value.
  • .append() will add the new value to the existing value.

Unless I know I need multiple values on my header, I stick with .set(). This preference is personal, and it stems from intent. By using .set() I feel it is clear that my intent is to add a new single-value header, where .append() suggests that I am adding a new multi-value header.

popularity
Electric
posted
Sep. 10, 2025