Reputation: 143
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
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
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
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
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
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