Having trouble sending an HTTP POST request with form-data from Angular app to Cache backend
I'm trying to send an HTTP POST request with form-data from an Angular app to a Cache backend, but my request fails with a 406 Not Acceptable error.
httpRequestHeaders = new HttpHeaders({ Authorization: 'Bearer ' + sessionStorage.getItem('access_token'), Accept: '' }); uploadFile(file: File) { const formData: FormData = new FormData(); formData.append("file", file); const req = new HttpRequest("POST", this.postURL, formData, { reportProgress: true, responseType: "json", headers: this.httpRequestHeaders, }); return this.http.request(req); }
Though I'm sending form-data, if I don't specify the Content-Type in the request header, it gets detected as "application/json" and I get the following message with my 406 error:
ERROR #5770: Object open failed because 'UniqueByRequest' key value of 'document:upload:class:POST::application/octet-stream' was not found
If I do specify Content-Type = "multipart/form-data", I get a 400 Bad Request error and no response/error message. Looking closer into the request headers, I notice that the boundary isn't getting set when I specify the Content-Type and suspect this may be the cause of the 400 error.
Has anyone experienced a similar issue before and know of a workaround?
Hi
I would expect the content type to be 'application/json'? (I assume the responseType is the contentType? In every HTTP Operation I have worked with that used json that was the content type).
The character set must be set to UTF-8 unless you need to use the Latin character set in which case use Latin. Bear in mind, both the server and the client must be consistent in declaring what they are sending and what they are expecting to receive.
I found the following article on Angular and HTTP (or Interceptors as they are called after Angular 5)
HttpHeaders
We add HTTP Headers using the HttpHeaders helper class. It is passed as one of the arguments to the
GET
,POST
,PUT
,DELETE
,PATCH
&OPTIONS
request.To use
HttpHeaders
in your app, you must import it into your component or serviceThen create an instance of the class
And then call the
httpClient.get
method passing the headers as the argumentNote that
httpHeaders
are immutable. i.e every method onHttpHeaders
object does not modify it but returns a newHttpHeaders
object.The
httpHeaders
class has several methods using which you can manipulate the headers.set
set(name: string, value: string | string[]): HttpHeaders
The Sets method returns a new instance after modifying the given header. If the header already exists, its value is replaced with the given value in the returned object.
httpHeaders are immutable
The HTTP headers are immutable. The following example does not work as each
set
method returns a new header and does not update the original header.To workaround, you can use the code as follows
You can also use the following code
append
append(name: string, value: string | string[]): HttpHeaders
The append method appends a new value to the existing set of values for a header and returns a new instance. The append method does not check if the value exists.
The above results in
content-type
header in the request header ascontent-type: application/json,application/x-www-form-urlencoded
has
has(name: string): boolean
Returns true if the given header with the name already exists in the
HttpHeaders
. The following code checks if thecontent-type
header present in the request header. If not it adds it.Thanks for the input Nigel! The issue turned out to be caused by an HTTP interceptor from an imported library which would set the Content-Type to application/json if it was undefined.
Finally fixed the problem by adding a new HTTP interceptor to remove the Content-Type header if the request URL matched a specific pattern (i.e. contained "$upload"). Removing the Content-Type header allowed the Content-Type to get auto-detected as "multipart/form-data" and the boundary to get set when the request was sent.