Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.net core 2.2 & Angular 7: IFormFile in file upload controller is always null

When looking at other answers and some google, everything seems to be fine, yet my controller never receives any data.

Api uris and such are correct, the request arrives at the correct controller

Angular snippet:

component.html - my input field

<div class="input-group">
    <input type="file" #fileInput id="fileInput" (change)="stageFile()"
           accept="csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel">
    <div class="input-group-append">
        <button class="btn btn-primary" type="button" (click)="fileUpload()" [disabled]="!staged || uploading">
          <span *ngIf="!uploading,else loadAnim">Upload</span>
          <ng-template #loadAnim>Uploading...</ng-template>
        </button>
    </div>
</div>

component.ts - get data from view

@ViewChild('fileInput') fileInput;
private file: File;
public uploading = false;
public staged = false;

constructor(private uploadService: UploadService) { }

public stageFile(): void {
    this.staged = true;
    this.file = this.fileInput.nativeElement.files[0];
    console.log(this.file)
}

public fileUpload():void {
    this.uploading = true;
    if (this.file != null)
      this.uploadService.upload(this.file).subscribe();
    this.staged = false;
    this.uploading = false;
}

services.ts - handle actual ajax call

private uploadURI = environment.dataServiceURI + '/upload';

constructor(private http: HttpClient) {}

public upload(file: File): Observable<object> {
// create multipart form for file
let formData: FormData = new FormData();
formData.append('file', file, file.name);

const headers = new HttpHeaders().append('Content-Type', 'mulipart/form-data');

// POST
return this.http
  .post(this.uploadURI, formData, {headers: headers})
  .pipe(map(response => response));
}

.net core snippet

It is here where IFormFile file always contains null and thus my result is always 500

[HttpPost("upload")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public IActionResult ParseData([FromForm(Name = "file")] IFormFile file)
{
    if (file == null)
       return StatusCode(500);
    (...)
    return Ok()
 }

Request Payload Info

From browser networking

------WebKitFormBoundarycBigaNKzS4qNcTBg 
Content-Disposition: form-data; name="file"; filename="test_data_schema.xlsx" 
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

------WebKitFormBoundarycBigaNKzS4qNcTBg--
like image 765
pjominet Avatar asked Mar 05 '19 17:03

pjominet


Video Answer


2 Answers

Problem solved:

in service.ts it should be

const headers = new HttpHeaders().append('Content-Disposition', 'multipart/form-data');

instead of

const headers = new HttpHeaders().append('Content-Type', 'multipart/form-data');

Also in the .net controller, adding or removing [FromForm(Name = "file")] as parameter prefix does not change the behavior. It works perfectly fine with or without it. As hugo pointed out in the comments it's convention based as long as the param name matches to name in the form data.

like image 175
pjominet Avatar answered Sep 21 '22 22:09

pjominet


Agree, the Content-Disposition header did help. One more condition should be met: the first parameter of formData.append(....) method: the first parameter of

formData.append(...)

method:

enter image description here should be the same with the name of agrument in controller action:

enter image description here

like image 34
Viktor Fursov Avatar answered Sep 21 '22 22:09

Viktor Fursov