0

I am here trying to post some data from Angular App to spring boot backend, and unfortunately, I am stuck with an incomprehensible bug for a day,

This is my API

@PostMapping("/add", consumes = ["multipart/form-data"])
fun addTeam(
    @RequestPart(name = "file") file: MultipartFile,
    @RequestPart(name = "body") team: Team
): ResponseEntity<*> {
    val imgUrl = filesStorageService.storeFile(file)

    val fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
        .path("/storage/downloadFile/")
        .path(imgUrl)
        .toUriString()


    val list = teamService.addTeam(team, fileDownloadUri)
    return ResponseEntity(list, list.status)
}

and here's the Angular API call

addTeam(team: Team, coverFile: File): Observable<boolean> {
return new Observable<boolean>(subscriber => {
  let formDate = new FormData();
  formDate.append('file', coverFile);
  formDate.append('body', JSON.stringify(team));
  this
    .client
    .post<ResponseWrapper<Boolean>>(environment.BASE_URL + this.ADD_TEAM, formDate, {
      headers: {'Content-Type': 'multipart/form-data'},
     })
......

so here I got an exception saying

org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found

so I found some solutions tell to set the angular content type to undefined but this also did not work then I removed the content type from the angular call

but this gives me another error

2020-12-12 19:12:41.298  WARN 16892 --- [nio-8080-exec-9] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/octet-stream' not supported]

so I made the spring app accepts application/octet-stream but it results ,

2020-12-12 19:14:39.775  WARN 16796 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data;boundary=----WebKitFormBoundarykunWjFPmOyVdc8vn' not supported]

so can anyone help me through this?

Also, I tried this API using postman and it's working when I put content type to multipart/form-data

m.yuki
  • 815
  • 1
  • 10
  • 19
  • Why do you add this as part of FormData `formDate.append('body', JSON.stringify(team));`? – Nicholas K Dec 12 '20 at 17:20
  • this part to send the body of `team` as a json, the problem is that all thing is working on postman ! but not with angular – m.yuki Dec 12 '20 at 17:22
  • FormData is only for the file contents. You cannot append another *request body* to it, hence it fails. – Nicholas K Dec 12 '20 at 17:30
  • As far as I have seen, you can send only a single request body from angular. This is the signature of the *http.post* : `post(url: string, body: any, options?: RequestOptionsArgs) : Observable`. Multiple headers are allowed, but as you can see not multiple request body's. – Nicholas K Dec 12 '20 at 17:33
  • so this means I cannot send the request like what I did with postman? – m.yuki Dec 12 '20 at 17:37
  • Most probably no. Just curious, why does your API require both a file as well as another json input? Looks like you might have to re-define it. – Nicholas K Dec 12 '20 at 17:38
  • I removed the body from my API also from angular to only trying to upload the file and it's giving `org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found` – m.yuki Dec 12 '20 at 17:38
  • [This](https://stackoverflow.com/questions/36005436/the-request-was-rejected-because-no-multipart-boundary-was-found-in-springboot) and [this](https://stackoverflow.com/questions/17462642/spring-rest-the-request-was-rejected-because-no-multipart-boundary-was-found) could help you out with that exception. – Nicholas K Dec 12 '20 at 17:43

3 Answers3

1

Maybe you can try this one in your angular app:

formDate.append('file', coverFile);
formDate.append('body', new Blob([JSON.stringfy(team)], { type: 'text/plain' }));

And now, in your Spring, change the type of the team to string:

@PostMapping("/add", consumes = ["multipart/form-data"])
fun addTeam(
    @RequestPart(name = "file") file: MultipartFile,
    @RequestPart(name = "body") team: String
): ResponseEntity<*> {

Now, after you get the result of the body, you can parse it into an object with your spring.

Titus Sutio Fanpula
  • 3,467
  • 4
  • 14
  • 33
1

I recently faced this problem, but with NestJS on the back-end and adding a file name as a third parameter to the append() function helped.

formDate.append('file', coverFile, '<FILE_NAME_HERE>');

Also I think you don't need to specify 'Content-Type' header explicitly, Angular detects and sets it automatically.

igor_c
  • 1,200
  • 1
  • 8
  • 20
0

after trying many solutions, I finally found that if I want to post many parts in angular I should include the body of json value as a json blob with it's type , and no need to specify the content type of the request itself

just like this ,

formData.append('body', new Blob([JSON.stringify(team)], {
    type: 'application/json'
  }));
m.yuki
  • 815
  • 1
  • 10
  • 19