Angular File Upload

We will know that how to create a functional Angular file upload component that requires a file of a given extension to be uploaded and sends the file to the backend via an HTTP POST call.

The custom component will have an upload loading indicator and will support upload cancellation. We will give an example (in Node) of handling a file in the backend.

How to Upload Files to the Browser

To create an Angular file upload component, we first need to understand how to upload files in plain HTML and JavaScript and take it from there.

The main component for uploading files to the browser is a plain HTML input of the file type:

This input will allow the user to open the browser file selection dialog and select one or more files (by default). Here's what the input looks like:

Angular File Upload

You can select a file from file input box, and then with a little JavaScript, you can send it to the backend.

Why don't we see file input often?

The problem with this plain file input is that it's very hard to style by default. Some applied styles can't be changed, and we can't even change the text on the button!

It is the default browser behavior that cannot be changed and is the reason why we don't see this plain file input on the interfaces we use daily, like Gmail, etc.

Because it is impossible to style this file input properly, the most common option is never to show it to the end-user.

How does the input of type file work?

When the user selects a file using the file upload dialog, an event of type

The change will be emitted. The event will then contain the list of files the user has selected on the target.

Here is the output we see on the console after the user selects the file:

{
  lastModified: 1601984029839
  lastModifiedDate: Tue Oct 06 2020 13:33:49 GMT+0200 (Central European Summer Time) 
  name: "angular-forms-course-small.jpg"
  size: 56411
  type: "image/jpeg"
  webkitRelativePath: ""
}

When the change event is triggered, the browser's file is not automatically uploaded to the backend. Instead, we'll need to trigger an HTTP request ourselves in response to the change event.

Creating the User Interface of the File Upload Component

It is impossible to properly style a plain input of a file, we hide it from the user and then build an alternate file upload UI that uses the file input behind the scenes.

Template for the initial file upload component:

The user interface is divided into two different parts. At the top, we have a plain file input, which is used to open the file upload dialog and handle the change event.

This plain input text is hidden from the user, as we can see in the component CSS:

We have the file-upload container div, which contains the actual UI that the user can see on the screen.

For example, we built this UI with Angular Material components, but of course, the optional file upload UI can take any form you like.

This UI can be a dialog, a drag and drop zone, or, as in the case of our component, simply a styled button:

Angular File Upload

Notice in the component template how the upload blue button and the invisible file input are connected. When the user clicks the blue button, a click handler triggers the file input via fileUpload.click().

The user would then select a file from the file upload dialog, and the change event would be triggered and handled by onFileSelected().

Uploading file to backend using Angular HTTP client

Now let's take a look at our component class and implementation onFileSelected():

Here is the component:

We are getting a reference to the files that the user has selected by accessing events. Target. Files property.

Then we create the form payload using the FormData API. It is a standard browser API and is not Angular-specific.

We use the Angular HTTP client to make HTTP requests and send the file to the backend.

At this point, we will already have a working file upload component.

How to display file upload progress indicator

We are adding a few more elements to the UI of our file upload component. Here is the file upload component template:

The two main elements we've added to the UI are:

  • An Angular Material progress bar, which is visible only when the file upload is still in progress.
  • An Upload Cancel button, also visible only if an upload is still in progress

How do you know how much file has been uploaded?

We implement the progress indicator by using the report progress feature of the Angular HTTP client.

With this feature, we can get notified of the progress of file uploads through multiple events emitted by HTTP Observables.

To see this in action, let's take a look at the final version of the FileUpload component class, which has all its features implemented:

As we can see, we have set the ReportProgress property to true in our HTTP call, and we have also set the Overview property in the Value event.

We will receive an event object reporting the progress of the HTTP request.

These events will be emitted as the value of http$observable and come in different types:

  • Upload Progress type events report the percentage of a file that has already been uploaded.
  • Events of the type Feedback report that the upload is complete
  • By using events of type UploadProgress, we are saving the ongoing upload percentage in a member variable UploadProgress, which we use to update the value of the progress indicator bar.
  • When the upload completes or fails, we need to hide the progress bar from the user.

We can be sure to do this by using the RxJs finalize operator, which will call the reset() method in both cases: upload success or failure.

How to cancel an ongoing file upload

To support file upload cancellation, we must refer to the RxJs subscription object when the http$observable is subscribed.

In our component, we store this membership object in the uploadSub member variable.

While the upload is still in progress, the user can cancel it by clicking the Cancel button. Then the cancelUpload() upload method is invoked, and the HTTP request can be canceled by unsubscribing from the UploadSub subscription.

Canceling this subscription will immediately cancel the ongoing file upload.

How to accept certain type of files

In the final version of our file upload component, we can require the user to upload a certain type of file using the required file type property:

This property is passed to the file input's accept property in the file upload template, forcing the user to select a PNG file from the file upload dialog.

How to Upload Multiple Files

The browser file selection dialog will allow the user to select only one file to upload by default.

But by using the Multiple properties, we can allow the user to select multiple files:

Note that this will require a complete different UI than the one we created. A style upload button with a progress indicator works well for uploads of only one file.

For a multi-file upload scenario, various UIs can be created: a floating dialog with the upload progress of all files, etc.

Handling uploaded file on node backend.

The way you handle an uploaded file in your backend depends on the technology you use, but let's give a quick example of how to do it using the Node and Express frameworks.

We need to install the express-fileupload package first. Then we can add this package as middleware to our express application:

We have to do is define an express route to handle file upload requests:

Summary

The best way to handle file uploads in Angular is to build one or more custom components based on the supported upload scenarios.

The file upload component must contain an HTML input type file that allows users to select one or more files from the file system.

This file input is hidden from the user as it is not stylable and should be replaced by a more user-friendly UI.

By using the file input in the background, we can refer to the file through the change event, which we can then use to make an HTTP request and send the file to the backend.






Latest Courses