angular: Form data is empty when calling http.post() with ContentType header

I’m submitting a … (check one with “x”)

[x] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

var fd = new FormData();
fd.append('field', 'value');

// fires an empty request (in Chrome Developer Tools)
this.http.post('http://google.com', fd,
{headers: new Headers({'Content-Type': 'application/x-www-form-urlencoded'}))
 .subscribe(() => console.log("request done with success"));

The request data is empty (as seen in Chrome Developer Tools).

Expected behavior

The request should not be empty (and have the same body as if the Content-Type wasn’t changed).

Minimal reproduction of the problem with instructions

Plunker with two requests, one valid (Content-Type wasn’t changed), one failing (Content-Type was changed) http://plnkr.co/edit/7PEsXmJ8dLN3CYx7hQaE?p=preview

Please tell us about your environment:

  • Angular version: 2.0.0
  • Browser: Chrome Latest
  • Language: TypeScript

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 27 (7 by maintainers)

Commits related to this issue

Most upvoted comments

I don’t know if it helps anyone, but after spending quite some time I found out that when using FormData we don’t have to set the content type to ‘multipart/form-data’.

Removing the code which was setting the content type to ‘multipart/form-data’ worked for me.

Would like someone to shed some light into it.

I had the same issue using fetch one time, I managed to workaround using the following function :

getFormUrlEncoded(toConvert) {
		const formBody = [];
		for (const property in toConvert) {
			const encodedKey = encodeURIComponent(property);
			const encodedValue = encodeURIComponent(toConvert[property]);
			formBody.push(encodedKey + '=' + encodedValue);
		}
		return formBody.join('&');
	}

And calling it this way :

const field = {field: 'value'};
     // failed request
    this.http.post('http://google2.com', this.getFormUrlEncoded(field),
    {headers: new Headers({'Content-Type': 'application/x-www-form-urlencoded'}))
     .subscribe(() => console.log("request done with success"));

I’m not sure this is a durable solution, but it might help you in short time periods :

http://plnkr.co/edit/fNhsjvusWn8mVfweMY9l?p=info

This issue has not been fixed yet as of latest version

even multipart/form-data has also similar issue. not able to add the file content to the FormData.

let formData: FormData = new FormData(); formData.append(‘file’, file, file.name); formData.append(‘entityNumber’,this.node.number); formData.append(‘itemType’,getFileExtensionByDomainAndTab(this.node.baseModel.domainId,this.node.baseModel.dtoType));

let headers = new Headers();
headers.append('Content-Type', 'multipart/form-data;boundary='+Math.random());
headers.append('Accept', 'application/json');

this.http.post(`/file/fileupload`, formData, headers)
  .map(res => res.json())
  .catch(error => Observable.throw(error))
  .subscribe(
    data => {
      this.attachments.push(data);
      this.attachmentSubject$.next(data);
    },
    error => {
      alert("failed to upload");
    }
  )

Angular: About to use multipart/form-data

Me: Please use multipart/form-data

Angular: How dare you 🖕

Thank You @PratikTheGameDever ,

Removing ( ‘Content-Type’, ‘multipart/form-data’ ) Solved my issue with httpClient

😠 I spent almost 4 hours at debuging this annoying issue… Newest version of Angular has this problem too. If I remove my headers it works, but… API requires these all.

@PratikTheGameDever God bless ur soul, I have been on this issue whole damn day… thank you

@ritikrishu thanks. Your solution works very well. But my issue laid my side laid. I appended Content-Type header but it was incorrect way to make multipart request.

Here is a working solution with Reactive forms, but a similar setup will work with template driven forms as well. template:

<form [formGroup]="form" ngSubmit="postForm()">
    <input type="file" formControlName="file" (change)="onFileChange($event)">
    <button type="submit">Upload</button>
</form>

component:

import { HttpClient, HttpParams, HttpRequest } from '@angular/common/http';
import { FormBuilder, Validators } from '@angular/forms';
import { Component } from '@angular/core';

@Component({
    selector: 'my-selector',
    templateUrl: 'my-selector.component.html',
    styleUrls: ['my-selector.component.scss']
})

export class MyComponent {
    constructor(
        private http: HttpClient,
        private fb: FormBuilder
    ) { }

    file

    form = this.fb.group({
        file: [null, Validators.required]
    })

    postForm() {
        const formData = new FormData();
        formData.append('excel', this.file);

        const params = new HttpParams();

        const options = {
            params,
            reportProgress: true,
        };

        const req = new HttpRequest('POST', 'http://0.0.0.0:4000/v1/matric', formData, options);
        this.http.request(req).subscribe(console.log)
    }

     onFileChange(event) {
        if (event.target.files && event.target.files.length) {
            const [file] = event.target.files;
            this.file = file
        }
    }
}

After consideration, I’m considering this a feature request, not a bug.

FormData is exclusively designed for encoding multipart/form-data. It’s not compatible with application/x-www-form-urlencoded - URLSearchParams is a better (supported) body type for that encoding.

It would be a new feature to support conversion of FormData to URL-encoded format. Not all FormData instances can be converted, either - file uploads for example cannot be URL-encoded.

For that reason, I don’t think this would be a good feature to implement. If you have a FormData instance you want to URL-encode, perform that encoding before passing it to Http.

In the future, a user-defined interceptor could convert FormData to a URL-encoded form automatically.