Angular 5 and Asp.net Core File Upload

There are lots of help for ASP.NET mvc file upload in the web. But i got difficulty when need to implement Angular 5 using ASP.NET core. Moreover i have used AspNetBoilerplate framework 🙂 So my file uploading technologies stack is like below

Back-end implementation:

Boilerplate App service does not work for file upload. So i have created standard controller for file upload end point.

[DisableValidation]
public class TestAppFileUploadController : TestControllerBase
{
[HttpPost]
public async Task<IActionResult> UploadFile(IFormFile file)
{
  if (file == null || file.Length == 0)
    return Content("file not selected");
 var filePath = Path.Combine(
 Directory.GetCurrentDirectory(), "TempUpload");

 if (!Directory.Exists(filePath))
 {
    Directory.CreateDirectory(filePath);
 }

 var fileUniqueId = Guid.NewGuid().ToString().ToLower().Replace("-", string.Empty);
 var uniqueFileName = $"{fileUniqueId}_{file.FileName}";

 using (var fileStream = new FileStream(Path.Combine(filePath, uniqueFileName), FileMode.Create))
 {
     await file.CopyToAsync(fileStream);
 }

 var result = new
 {
    UploadFileName = uniqueFileName
 };

 return new JsonResult(result);
 }
}

This file upload end point accept single file. If need to accept multiple, the parameter should be like List<file>. The parameter name “file” is important. This name must have to match the angular form data name value. Another important point is that we have applied [DisableValidation] attribute for controller(also work in action level) to avoid form data validation checking of Boilerplate Framework middle-ware(Ref 2).

DotNet core has removed “Request.Files” object form “HttpContext” directly. So collecting the file object from “Request” not possible in Dotnet core. Alternatively DotNet core suggest to add “IFormFile” in action parameter. I think this is absolutely right move of the core 🙂

Angular Implementation:

Component HTML template:

<p-fileUpload

name="myFile[]"

maxFileSize="1000000000"

customUpload="true"

auto="auto"

(uploadHandler)="myUploader($event)"

(onUpload)="onUpload($event)"

(onBeforeSend)="onBeforeSend($event)">

<ng-template pTemplate="content">

   <ul *ngIf="uploadedFiles.length">

     <li *ngFor="let file of uploadedFiles">{{file.name}} - {{file.size}} bytes</li>

   </ul>

   </ng-template>

</p-fileUpload>

Angular Component:


export class FileUploadComponent extends AppComponentBase {

uploadUrl: string;

uploadedFiles: any[] = [];

constructor(

injector: Injector,

private http: Http

) {

super(injector);

  this.uploadUrl = 'http://localhost:22742/TestAppFileUpload/UploadFile';

}

myUploader(event):void{

  console.log('My File upload',event);

   if(event.files.length == 0){

      console.log('No file selected.');

     return;

    }

  var fileToUpload = event.files[0];

  let input = new FormData();

  input.append("file", fileToUpload);

  this.http

    .post(this.uploadUrl, input)

    .subscribe(res => {

    console.log(res);

  });
}

// upload completed event

onUpload(event): void {

  for (const file of event.files) {

     this.uploadedFiles.push(file);

  }

}

onBeforeSend(event): void {

  event.xhr.setRequestHeader('Authorization', 'Bearer ' + abp.auth.getToken());

}

}

The method myUploader is important here. We have used customUpload=”true” for PrimeNg upload, using “myUploader” actually we are posting uploading request manually. The form data “file” text must have to match with backend controller action method variable name.

Reference:

  1. https://devblog.dymel.pl/2016/09/02/upload-file-image-angular2-aspnetcore
  2. forum.aspnetboilerplate.com
  3. https://www.primefaces.org/primeng/#/fileupload
Advertisements