Uploading Image from Angular to ASP.NET Core Web API

avatar

In this post we will be discussing about creating an application where you can upload image from angular 8 to ASP.NET Core Web API using ASP.NET Boilerplate. In this we will be going through Back End first i.e. ASP.NET Core part and then we will go through the frontend i.e. Angular.

I have written a function UploadProfilePicture in UserAppService which will handle the upload of profile pic and then create image on a predefined location.

The logic behind it very straight forward where we are providing the path where the file will be stored. We check if the directory exists or not, if not then creating the directory. Then we are creating the file stream object and then storing the file in that location.

public async Task<string> UploadProfilePicture([FromForm(Name = "uploadedFile")] IFormFile file, long userId)
{
  if (file == null || file.Length == 0)
    throw new UserFriendlyException("Please select profile picture");

  var folderName = Path.Combine("Resources", "ProfilePics");
  var filePath = Path.Combine(Directory.GetCurrentDirectory(), folderName);

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

  var uniqueFileName = $"{userId}_profilepic.png";
  var dbPath = Path.Combine(folderName, uniqueFileName);

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

  return dbPath;
}

Few things to note here :

  1. IFormFile object will come as null if the name attribute of the file input is not same as that of the name of the parameter used in the controller. So you should name then same or use [FromForm(Name = "")] and then assign the name as shown below.

  2. Since we are creating a new directory we need to tell ASP.NET Core to serve the static files from that location. For that we need to modify the Configure method of Startup.cs class as shown below :

app.UseStaticFiles(new StaticFileOptions()
{
 FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), @"Resources")),
 RequestPath = new PathString("/Resources")
});
  1. When using IFormFile, the swagger will give you multiple text boxes like ContentType, ContentDisposition, Headers, Length, Name, FileName etc instead of file upload control. To change the textboxes to the actual file upload control we need to implement IOperationFilter and then implement the apply method as shown below. The main part is type where we need to define file, since we are clearing all the previous parameters we also need to add the user id parameter.
using Swashbuckle.AspNetCore.Swagger;

using Swashbuckle.AspNetCore.SwaggerGen;

namespace LetsDisc.Web.Host.Startup
{
 public class FileUploadOperation : IOperationFilter
 {
  public void Apply(Operation operation, OperationFilterContext context)
  {
   if (operation.OperationId.ToLower().Contains("upload")))
   {
    operation.Parameters.Clear();
    operation.Parameters.Add(new NonBodyParameter
        {
          Name = "uploadedFile",
          In = "formData",
          Description = "Upload File",
          Required = true,
          Type = "file"
        });
    operation.Parameters.Add(new NonBodyParameter
        {
          Name = "userId",
          In = "query",
          Description = "",
          Required = true,
          Type = "long"
        });
    operation.Consumes.Add("multipart/form-data");
   }
  }
 }
}

Thus we are finished with the backend, now we will go forward with the frontend implementation.

HTML

In HTML we will have an input of type file and then we have both change and click function so that user can upload the same image twice.

<div class="col-md-3 profile-image-edit">
 <label class="hoverable" for="fileInput">
 ... img tag
  <span class="hover-text">Choose file</span>
  <span class="background"></span>
 </label>
 <br />
 <input #fileInput id="fileInput" type='file' (click)="fileInput.value = null" value="" (change)="onSelectFile($event.target.files)">
 <button class="btn btn-default" *ngIf="url" (click)="delete()">delete</button>
</div>

CSS

.hoverable {
    position: relative;
    cursor: pointer;
    height: 150px;
    width: 150px;
    border-radius: 50%;
}

    .hoverable .hover-text {
        position: absolute;
        display: none;
        top: 50%;
        left: 50%;
        transform: translate(-50%,-50%);
        z-index: 2;
    }

    .hoverable .background {
        position: absolute;
        display: none;
        top: 0;
        left: 0;
        bottom: 0;
        right: 0;
        background-color: rgba(255, 255, 255, 0.5);
        pointer-events: none;
        border-radius: 50%;
        z-index: 1;
    }

    .hoverable:hover .hover-text {
        display: block;
    }

    .hoverable:hover .background {
        display: block;
    }

Code Behind

In the code behind we will have a function which has a fileReader ojject to preview the image as well as we will be calling our backend service for uploading the image.

onSelectFile(files: FileList) {
        
  if (files.length === 0)
    return;
        
  this.fileToUpload = files.item(0);

        
  const fileReader: FileReader = new FileReader();
  fileReader.readAsDataURL(this.fileToUpload);

  fileReader.onload = (event: any) => {
    this.url = event.target.result;
  };

  this.files.push({ data: this.fileToUpload, fileName: this.fileToUpload.name });

  this._userService.uploadProfilePicture(this.files[0], this.user.id)
    .subscribe((result: string) => {
      this.userDetails.profileImageUrl = result;
  });
}

delete() {
  this.url = null;
}

GitHub Commit: https://github.com/codingdefined/LetsDisc/commit/ab7af63ba3cf94c23278fc2fe00d3769672bf506


Also Published: CodingDefined.com



0
0
0.000
6 comments
avatar

Thank you so much for participating in the Partiko Delegation Plan Round 1! We really appreciate your support! As part of the delegation benefits, we just gave you a 3.00% upvote! Together, let’s change the world!

0
0
0.000
avatar

Oh this looks very interesting.
My office still on ASP. NET but I am weighing on whether to learn image upload via asp.net or php.

Posted using Partiko Android

0
0
0.000
avatar

Being on ASP.NET is not a problem if you are using ASP.NET Core which in my opinion is much better than the classic ASP.NET Framework :).

0
0
0.000
avatar

I actually have not venture out to asp.net core yet.

Posted using Partiko Android

0
0
0.000
avatar

I was working with ASP.NET for like 5 years and then shifted to Angular + ASP.NET Core from the last year or so.

0
0
0.000
avatar

Hi @codingdefined!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your UA account score is currently 5.033 which ranks you at #1116 across all Steem accounts.
Your rank has dropped 15 places in the last three days (old rank 1101).

In our last Algorithmic Curation Round, consisting of 132 contributions, your post is ranked at #27.

Evaluation of your UA score:
  • You've built up a nice network.
  • The readers like your work!
  • Great user engagement! You rock!

Feel free to join our @steem-ua Discord server

0
0
0.000