56

I know there are a lot of questions about this, but I can't get this to work:

I want to upload a file from input to a server in multipart/form-data

I've tried two approaches. First:

headers: {
  'Content-Type': undefined
},

Which results in e.g. for an image

Content-Type:image/png

while it should be multipart/form-data

and the other:

headers: {
  'Content-Type': multipart/form-data
},

But this asks for a boundry header, which I believe should not be manually inserted...

What is a clean way to solve this problem? I've read that you can do

$httpProvider.defaults.headers.post['Content-Type'] = 'multipart/form-data; charset=utf-8';

But I don't want all my posts to be multipart/form-data. The default should be JSON

6 Answers 6

87

Take a look at the FormData object: https://developer.mozilla.org/en/docs/Web/API/FormData

this.uploadFileToUrl = function(file, uploadUrl){
        var fd = new FormData();
        fd.append('file', file);
        $http.post(uploadUrl, fd, {
            transformRequest: angular.identity,
            headers: {'Content-Type': undefined}
        })
        .success(function(){
        })
        .error(function(){
        });
    }
Sign up to request clarification or add additional context in comments.

5 Comments

Just confirmed and IE 9 must no longer be supported for this project, so this is perfect for me! Thx!
This works but why does the Content-Typehas to be set to undefined ?
@meucaa The code snippet looks similar to what's on this blog post which states: "By setting ‘Content-Type’: undefined, the browser sets the Content-Type to multipart/form-data for us and fills in the correct boundary. Manually setting ‘Content-Type’: multipart/form-data will fail to fill in the boundary parameter of the request." - uncorkedstudios.com/blog/…
instead of file if i have base64(blob) how can i upload ? @jstuartmilne
I am working with an ASP.NET Web API backend, and this is exactly what was needed! I didn't need the transformRequest bit, however. Thank you!
38

Here's an updated answer for Angular 4 & 5. TransformRequest and angular.identity were dropped. I've also included the ability to combine files with JSON data in one request.

Angular 5 Solution:

import {HttpClient} from '@angular/common/http';

uploadFileToUrl(files, restObj, uploadUrl): Promise<any> {
  // Note that setting a content-type header
  // for mutlipart forms breaks some built in
  // request parsers like multer in express.
  const options = {} as any; // Set any options you like
  const formData = new FormData();

  // Append files to the virtual form.
  for (const file of files) {
    formData.append(file.name, file)
  }

  // Optional, append other kev:val rest data to the form.
  Object.keys(restObj).forEach(key => {
    formData.append(key, restObj[key]);
  });

  // Send it.
  return this.httpClient.post(uploadUrl, formData, options)
    .toPromise()
    .catch((e) => {
      // handle me
    });
}

Angular 4 Solution:

// Note that these imports below are deprecated in Angular 5
import {Http, RequestOptions} from '@angular/http';

uploadFileToUrl(files, restObj, uploadUrl): Promise<any> {
  // Note that setting a content-type header
  // for mutlipart forms breaks some built in
  // request parsers like multer in express.
  const options = new RequestOptions();
  const formData = new FormData();

  // Append files to the virtual form.
  for (const file of files) {
    formData.append(file.name, file)
  }

  // Optional, append other kev:val rest data to the form.
  Object.keys(restObj).forEach(key => {
    formData.append(key, restObj[key]);
  });

  // Send it.
  return this.http.post(uploadUrl, formData, options)
    .toPromise()
    .catch((e) => {
      // handle me
    });
}

1 Comment

then the problem is IE 11
6

In Angular 13 (~13.0.0) isn't need to specify Content-Type of request.

some.service.ts:

public sendFiles(data: any): Observable<any> {
    const formData = new FormData();

    data.files.forEach((file: File) => {
      formData.append('files', file);
    });
    
    const url: string = <YOUR_API_URL>;

    return this.http.post<any>(url, formData);
}
  • Set Content-Type field to the following values ​​will result in error:
    • 'file'
    • undefined (can't with strict mode active)
    • 'multipart/form-data'

1 Comment

angular 15 does not need content type. github.com/bezkoder/angular-15-file-upload/tree/…
5

In Angular 6, you can do this:

In your service file:

 function_name(data) {
    const url = `the_URL`;
    let input = new FormData();
    input.append('url', data);   // "url" as the key and "data" as value
    return this.http.post(url, input).pipe(map((resp: any) => resp));
  }

In component.ts file: in any function say xyz,

xyz(){
this.Your_service_alias.function_name(data).subscribe(d => {   // "data" can be your file or image in base64 or other encoding
      console.log(d);
    });
}

Comments

2

In angular 9, Before tried 'Content-Type': undefined, but it is not worked for me then I tried the below code and It works like charms for a file object

const request = this.http.post(url, data, {
      headers: {
        'Content-Type': 'file'
      },
    });

Comments

1

Do not Set, Reset or Update the built in FormData's Content-Type. It will be solved. In Angular 7 it works.

Though there was an Auth-Interceptor But I did not let it set, change or reset my Content-Type header of my post request. Let it be what it is and the problem is solved.

Here is my auth interceptor image where I by passed my request

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.