Harshavardhan N
Harshavardhan N

Reputation: 143

How to remove Content Type set in HTTP Interceptors for uploading a file in angular4

In my application we set content-type = application/json in interceptor. But to upload a file content-type should be multipart/form-data ,i.e it will take contant-type = multipart/form-data when we try to upload form data. my question is how can I remove the content type set in interceptor while doing a post request to upload a file.

thanks, Harshavardhan

Upvotes: 11

Views: 13776

Answers (5)

Vikas
Vikas

Reputation: 12036

To Remove Existing header

 if (!req.headers.has('Content-Type')) {
 req = req.clone({ headers: req.headers.delete('Content-Type','application/json') });

Adding new Headers

req = req.clone({ headers: req.headers.set('Content-Type', 'multipart/form-data')})

To check the current value of the header.

req.headers.get('Accept')

Upvotes: 19

Banny
Banny

Reputation: 111

Check the incoming content type in interceptor headers like this:

intercept(request:HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>{

       // check whether we have form data
      if (request.body instanceof FormData) 
      {
            return request.clone({
           setHeaders:{
          'ContentType' : 'multipart/form-data',
           Authorization: `Bearer ${token}`

            }
          });
      }
       else{
             return request.clone({
          setHeaders:{
        'Content-Type': 'application/json',
         Authorization: `Bearer ${token}`
         }

         });
          }
        }

I hope that works for you!

Upvotes: 1

Rachit Losalka
Rachit Losalka

Reputation: 19

You can make use of in-built function delete provided by Angular's HttpHeaders.

const httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'my-required-content-type' }) }; httpOptions.headers.delete('Content-Type');

This way, you can set or delete specific headers with the use of names as keys.

Upvotes: 0

JoeriD
JoeriD

Reputation: 26

I'm using a Node.JS back-end which accepts normally the application/json content-type. One endpoint required a file, which needs to be send via a multipart/form-data form. This can be achieved by using the FormData interface.

So before sending the data from Angular to my back-end, I used the FormData interface:

onSubmit() {
  // ... some logic before

  // Need to post multipart/form-data to our server, so let's create a FormData instance:
  const formData = new FormData();
  formData.append('icon', this.selectedIcon, this.selectedIcon.name); // the actual file
  formData.append('name', this.createGroupForm.get('name').value); // other data from a Angular reactive form

  // Send the FormData to the service
  this.groupService.post(formData).subscribe((group) => {
    console.log({
      group,
    });
  });
}

Now it's actually easy with an Angular HttpInterceptor to detect if you are sending normal data or FormData, and changing the content-type header based on the instance of request.body:

export class ExampleInterceptor implements HttpInterceptor {
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    /**
     * Let's assume that we need to set the contentType to application/json for every request.
     */
    let contentType = 'application/json';

    /**
     * But when the data of the body is an instance of FormData, we can assume that we are uploading an file.
     * Therefore, we need to change the contentType to multipart/form-data.
     */
    if (request.body instanceof FormData) {
      // we are sending a file here
      contentType = 'multipart/form-data';
    }

    const clonedRequest= request.clone({
      setHeaders: {
        'content-type': contentType, // set the content-type here
      },
    });

    return next.handle(clonedRequest);
  }
}

Upvotes: 1

andrewjsaid
andrewjsaid

Reputation: 489

I had a similar problem and ended up solving it by calling toString() on the body to check whether it is form data.

I'm sure there is a cleaner way to check the type of an object, but this worked well enough for me:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    let ignore =
        typeof req.body === "undefined"
        || req.body === null
        || req.body.toString() === "[object FormData]" // <-- This solves your problem
        || req.headers.has("Content-Type");

    if (ignore) {
        return next.handle(req);
    }

    const cloned = req.clone({
        headers: req.headers.set("Content-Type", 'application/json')
    });
    return next.handle(cloned);
}

Note that I also ignore any requests where the Content-Type was manually specified.

Upvotes: 5

Related Questions