Question
Vivian Lee · Dec 20, 2021

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? 

1
0 3,571
Discussion (2)2
Log in or sign up to continue

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 service

Then create an instance of the class

And then call the httpClient.get method passing the headers as the argument

Note that httpHeaders are immutable. i.e every method on HttpHeaders object does not modify it but returns a new HttpHeaders 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 as content-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 the content-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.