1

I am trying to upload a csv file using Angular 4.

This is my controller in spring boot -

@PostMapping("/sop-master/csv-upload")
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public List<SopMasterDto> uploadCSV(@RequestParam("file") MultipartFile file, @RequestBody SopMasterDto sopMasterDto) throws IllegalStateException, IOException {
    return convertToDtos(sopMasterService.updateSopMaster(file, sopMasterDto.getUsername(),sopMasterDto.getPassword()), SopMasterDto.class);
}

And this is how I send my csv file in http post using Angular 4 -

uploadCSV(file: File) {
    let formData:FormData = new FormData();
    formData.append('file', file, file.name);

    let headers = new Headers();
    headers.append('Content-Type', 'multipart/form-data; boundary=Inflow');
    headers.set('Accept', 'application/json');
    let options = new RequestOptions({ 'headers': headers })

    return this.http.post(AppSettings.API_ENDPOINT + 'manage/sop-master/csv-upload/', formData, options)
        .map((res) => console.log(res))
        .catch(error => Observable.throw(error));
}

This is what I have in my view -

<input type="file" class="btn btn-default" accept=".csv" (change)="changeListener($event.target.files)">

changeListener (files: FileList) {
    if (files && files.length > 0) {
    let file: File = files.item(0);
    this.manageService.uploadCSV(file)
      .subscribe((response) => {
          this.refreshDatatable();
      });
    }
}

So file upload works absolutely fine when done through Postman but I keep getting this error when done through Angular 4 -

"status":400, "error":"Bad Request","exception":"org.springframework.web.multipart.support.MissingServletRequestPartException", "message":"Required request part 'file' is not present"

Update:

Attaching a screenshot of the error that appears on my browser console.

enter image description here

Request Headers

enter image description here

Request Header after removing custom boundary from request

enter image description here

Request Headers after removing content type from headers

enter image description here

Charmy Shah
  • 101
  • 2
  • 8

2 Answers2

1

I think your Problem is that you are sending @RequestParam("file") and @RequestBody together.

Try this:

@RequestMapping(value = "/sop-master/csv-upload", method = RequestMethod.POST, consumes = { "multipart/form-data" })
public List<SopMasterDto> uploadCSV(@RequestPart("file") MultipartFile file, @RequestPart("sopMasterDto") SopMasterDto sopMasterDto) {
....
}

and in Angular this:

let formData:FormData = new FormData();
    formData.append('file', file, file.name);
    formData.append('sopMasterDto', JSON.stringify(<your DTO ??? >))

    let headers = new Headers();
    headers.append('Content-Type', 'multipart/form-data');
    headers.set('Accept', 'application/json');
    let options = new RequestOptions({ 'headers': headers })

    return this.http.post(AppSettings.API_ENDPOINT + 'manage/sop-master/csv-upload/', formData, options)
        .map((res) => console.log(res))
        .catch(error => Observable.throw(error));

Vladimir
  • 612
  • 3
  • 16
1
  1. You are setting your custom boundy header to "inflow" but browser ignores it and uses own separator - server does not know how to split that multipart thus resulting in missing part
  2. Either browser is not showing the file content (normally it does) or you are not sending it at all - maybe File is not read properly

As for starters, dont use custom multipart boundry and let browser handle it. Some answers here Send multipart/form-data files with angular using $http suggests that it is not required to explicitly declare multipart content type - but nobody describes there is it sent as multipart. Try to focus on that topic.

Antoniossss
  • 31,590
  • 6
  • 57
  • 99
  • But if I remove the multipart boundary, I get a FileUploadException with this message 'Could not parse multipart servlet request;the request was rejected because no multipart boundary was found'. I am new at this, could you please help with a code. – Charmy Shah Apr 02 '19 at 07:04
  • Check the request when you remove your custom header. Maybe it is not multipart at all then. – Antoniossss Apr 02 '19 at 07:37
  • I have added a screenshot of my request headers above after removing the custom boundary. It seems to be multipart. – Charmy Shah Apr 02 '19 at 07:49
  • Check if this sents propert multipart for you. https://stackblitz.com/edit/angular-file-upload?file=app%2Fapp.component.ts Im not using crappy chrome btw. – Antoniossss Apr 02 '19 at 08:33
  • I can see that browser is not setting boundry in your case. Did you remove header at all? or you just skipped boundry? Anyway, there is working example in my previous comment. Compare network traffic with it. – Antoniossss Apr 02 '19 at 08:35
  • Oh, no I had removed only boundary from the headers. I did try without the header as well but got a MultipartException now saying 'Current request is not a multipart request'. I'll check out your example. – Charmy Shah Apr 02 '19 at 08:41
  • So what requrest is it if not multipart? Did you check that - for future - every change you make must include followup with request/response. Otherwise its useless to try to help you here. – Antoniossss Apr 02 '19 at 08:50
  • First focus on sending propert multipart since you are not sending a valid one. Then you can switch to "read" problems. – Antoniossss Apr 02 '19 at 08:51