Uploading files from Angular 4 to ASP.NET Core

Prerequisites

This article covers implementing some enhancements to an existing template, but having some experience with both Angular 4 and ASP.NET Core will help.

  1. Install software

Version Check

$ node --version
v6.11.0
$ npm --version
3.10.10
$ dotnet --version
2.0.2
  1. Create project
  • Run dotnet new angular
  • Upgrade Angular to ^4.3.0

Server components

ASP.NET Core provides the ability to handle form post using multipart/form-data. In order to access any of data we can use the Request.Form property. In our sample we want to work with the file uploads, and this is provided through Request.Form.Files. Essentially this maps to the files property on the client's <input type="file"> element.

Let's add a new Controller to handle the uploading. We can leverage the form files in order to read the data in, and respond back with a JSON object.

[HttpPost("/upload")]
public async Task<IActionResult> UploadAsync()
{
  using (var stream = Request.Form.Files[0].OpenReadStream())
  using (var streamReader = new StreamReader(stream))
  {
    string contents = await streamReader.ReadToEndAsync();
    return Ok(new {
      Contents = contents
    });
  }
}

Now that we have the API defined we can test it out by sending a request, and examining the response.

POST http://localhost:49292/upload HTTP/1.1
Host: localhost:49292
Content-Length: 200
Content-Type: multipart/form-data; boundary=347dbba4a085411b9630a9ffadfdcea5

--347dbba4a085411b9630a9ffadfdcea5
Content-Disposition: form-data; name="file"; filename="contents.txt"
Content-Type: text/plain

Lorem ipsum dolor sit amet
--347dbba4a085411b9630a9ffadfdcea5--

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Server: Kestrel
X-SourceFiles: =?UTF-8?B?YzpcdXNlcnNcamRiZXJfMDAwXGRvY3VtZW50c1x2aXN1YWwgc3R1ZGlvIDIwMTdcUHJvamVjdHNcV2ViQXBwbGljYXRpb24xMFxXZWJBcHBsaWNhdGlvbjEwXHVwbG9hZA==?=
X-Powered-By: ASP.NET
Date: Sun, 05 Nov 2017 04:51:09 GMT

29
{"contents":"Lorem ipsum dolor sit amet"}
0

Now that we have a working server API we can move onto the client.

Client components

As of Angular 4.3 the HttpClient class has been the defacto service for sending HTTP requests. We're going to use this to do the heavy lifting.

Note that when upgrading to Angular 4.3 you will need to make sure to import the HttpClientModule from @angular/common/http just as you would HttpModule.

We can inject the HttpClient, and mimic our test call in the Angular client:

upload(event: Event) {
  const inputElement = <HTMLInputElement>(event.srcElement || event.target);
  const files = inputElement.files;

  if (!files) return;

  const formData = new FormData();
  for (var index = 0; index < files.length; index++) {
    const file = files[index];
    formData.set(file.name, file, file.name);
  }

  this.httpClient.post<{contents: string}>('upload', formData)
    .subscribe(
      response => console.log(response),
      error => console.log(error));

  // Clear the value to allow uploading the same file again.
  inputElement.value = '';
}

Now we can run the app in a browser, and see the console results:

 {contents: "Lorem ipsum dolor sit amet"}

Wrapping it up

We've built out two things: an API which echoes a file's contents, and a view that uploads a file's contents to the API.

For some additional details check out this article's complete implementation on GitHub. For the detailed steps check out the repository's commit history.