Queue multiple files for uploading with Angular and ASP.NET Core 2.1

Björn Reinhardt
MAKONIS
Published in
4 min readJul 29, 2018

I assume that you have some basic knowledge of Angular and TypeScript and a little bit of ASP.NET Core. If not, I strongly recommend to dive into the offical tutorial which covers everything to savvy everything below.

You will also find the complete code here:
https://github.com/bjr001/angular-file-uploading-example

So your customer have this — of course agile — requirement which might look like this:

“As a user I want to upload multiple files without freezing the UI”.

Piece of cake, isn’t it? Go to Google, pick one of those what seems 10000 libraries, implement it and the job is done.

Yeah nice try…. while working with this fancy third party library you get the feeling the job might not be done that fast. You have to tweak a little bit here and there, have (mostly) multiple looks to the API documentation and/or make your way through endless answers on stackoverflow.

In the end you might ask yourself is it really that hard to do it on your own? Nope — it isn’t! I can tell you. In fact I can show you!

First and foremost let’s have a closer look on the functional requirements:

  • Queue multiple files
  • Have only one active upload
  • Don’t freeze UI
  • Get progress on every upload

I won’t go to much into non-functional requirements like to have smooth user experience and won’t show you how to implement the progress bar — at least not within this story ;)

Let’s stop the gibberish and let’s pound the keyboard. We’ll start with the easier one which is backend and go over to the frontend part.

Backend

Make your controller capable of getting files by the following code:

With IFormFile we’re using a builtin model binder to easily access information like content-type, length, name, filename and also get some very neat method to pass the file itself to a stream — thanks ASP.NET Core Team!

See also here:
https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-2.1#uploading-small-files-with-model-binding

Frontend

Regarding the frontend we have to do a little bit more. To give you a better understanding about the big picture I’ll show you a simplified class diagramm what we need to get the job done:

Instead of placing all our files to the root of our app-folder I’ll just create a seperate module:

ng g m file-upload

Which will produce the following code — don’t get confused by the UploadComponent (get their soon):

Now we’re going to create an enum to indicate the status of the uploading process:

ng g e file-upload/upload-status

Next we will create a class which actually represents the uploading file itself. The three methods complete(), failed() and updateProgress() will be responsible to control the state which in turn is the current status and progress:

ng g class file-upload/file-upload

So far so good right! Time to get to the centerpiece. The UploadService will be responsible to maintain the queue of files which we want to get uploaded. It also creates the request to upload the files which will then be executed by the Angular HttpClient.

To keep track of the queued files and their current progress we will make use of RxJS (which already comes with Angular since it’s heavily build on).

But how do we achieve this? As I mentioned before we will only create a proper HTTPRequest of type FormData which we will then pass to Angulars build-in HttpClient method request. Having a look at the description of this method we will see the following:

* Send the given `HttpRequest` and return a stream of `HttpEvents`.

Subscribing to this observable we will get notified about new HttpEventTypes where we can infer the current status and percentage of the active uploading progress. That’s exactly what we need!

The other tricky part is holding the queue which we will achieve by using BehaviorSubject which we will use because of some special features compared to Subject. The most emphasize feature for us is that is has some kind of state. That means it always returns a value when a consumer subscribes to it which won’t happend with a Subject and/or Observable. Of course this implies to have an initial value when creating a BehaviorSubject.

Why do we need this? Well... by implementing this behaviour we can ensure that our consumer/component can subscribe to the queue. Additionally we’ll be able to see progress of every file which has been pushed to the queue at any time.

For further information see http://reactivex.io/rxjs/manual/overview.html#behaviorsubject and also here https://stackoverflow.com/questions/39494058/behaviorsubject-vs-observable which gave me a better unterstanding.

Don’t forget to register your service within your module (FileUploadModule) or use the new decorator providedIn: root which we’ll do ;)

ng g service file-upload/upload

If you’re still with me we’re almost done! Last but not least we need some component which consumes our newly created service. For now let’s keep it simple and just use a plain button in order to upload your local files.

(I will show you in an upcoming article how to track progress and list uploading files in a queue)

ng g c file-upload/upload

And here we have it: No blackbox, no magic, no additional dependencies on 3rd party libraries!

Some pitfalls I was struggling with:

--

--