This guide covers all the practical aspects of managing file uploads within an Angular application.
We'll walk through the creation of a fully operational Angular file upload component that enforces a specific file extension and transmits the file to a server through an HTTP POST request.
This bespoke component will feature an upload progress indicator and support for upload cancellation. We'll also provide a Node-based example of how to process the incoming file on the server side.
Content Overview
Here are the main topics we'll address in this guide:
- The mechanics of file uploads in a web browser
- Constructing the interface for a file upload component
- Choosing a file from the filesystem via the upload dialog
- Transmitting a file to the server using the Angular HTTP Client
- Showing a visual indicator of upload progress
- Aborting an active file upload
- Processing the uploaded file on a Node server
- Uploading several files at once
- Wrap-up and final thoughts
Let's dive straight into building an Angular file upload component.
Browser-Based File Upload
To create an Angular file upload component, we first need to grasp how file uploads function using only standard HTML and Javascript.
The fundamental element for browser-based file uploads is a plain HTML input with the type set to file.
This input enables the user to launch the browser's file selection dialog and pick one or multiple files (by default, just one). Here's a visual representation of this input:

Once a file is chosen via this input box, a small amount of Javascript is all that's required to transmit it to a server.
The Rarity of Standard File Inputs
The main drawback of the standard file input is its inherent difficulty to style. Certain visual properties are immutable, and even the button's text cannot be customized.
This is unchangeable browser behavior, which explains why this raw input rarely appears in user interfaces we interact with daily, such as Gmail.
Since proper styling is impossible, the most practical approach is to simply hide it from the end-user, a strategy we'll adopt.
Functioning of the File Input
When the user picks a file via the selection dialog, a change event is fired. The list of chosen files is then accessible via the target.files property of this event.
The console output below shows what happens after a user selects a file:
When the change event is triggered, the browser does not automatically upload the file. Rather, we must trigger an HTTP request ourselves in response to this event.
With a clear understanding of the standard browser file upload process, we can now proceed to build an elegant Angular component to encapsulate it.
Designing the File Upload Interface
Given the styling limitations of a raw file input, the common practice is to conceal it from the user. In its place, we craft an alternative upload interface that operates the hidden file input indirectly.
An initial template for a file upload component might look like this:
This layout is divided into two sections. At the top sits the plain file input, tasked with opening the dialog and managing the change event.
This raw input is hidden from view using the component's CSS:
Below the invisible input, we have the file-upload container div, which holds the visible interface the user interacts with.
For demonstration purposes, this UI uses Angular Material components, but you are free to design the alternative interface in any way you see fit.
This interface could be a modal dialog, a drag-and-drop area, or, as in our case, a simple styled button:

Observe how the visible upload button and the invisible file input are connected in the template. Clicking the blue button triggers a click handler that invokes fileUpload.click() on the hidden input.
The user will then select a file from the dialog, which causes the change event to fire, subsequently handled by the onFileSelected() method.
Sending the File with Angular HTTP Client
Let's examine our component class and the implementation of the onFileSelected() method:
The component performs the following operations:
- It retrieves a reference to the user-selected files by reading the
event.target.filesproperty. - It constructs a payload using the
FormDataAPI, which is a standard browser API and not strictly Angular-related. - It then employs the Angular HTTP client to initiate an HTTP request to send the file to the server backend.
At this stage, we already have a functioning file upload component. However, to enhance it, we aim to incorporate a progress indicator and the capability to cancel an ongoing upload.
Implementing the Upload Progress Indicator
We'll enhance the interface of our file upload component by adding several elements. Here is the definitive template:
The new additions to the UI are:
- An Angular Material progress bar, shown only while the upload is actively in progress.
- A cancel action button, also displayed only when an upload is underway.
Determining Upload Progress
The progress indicator is implemented using the reportProgress feature of the Angular HTTP client.
This feature allows us to receive progress updates through multiple events emitted by the HTTP Observable.
To see this in practice, here’s the complete component class with all features implemented:
Notice that we've set the reportProgress property to true in the HTTP call, and also configured the observe property to the value events.
This configuration ensures that, as the POST request proceeds, we receive event objects that report the progress of the HTTP request.
These events pop up as values from the http$ Observable, each with a distinct type:
- Events classified as
UploadProgressindicate the percentage of the file that has been uploaded so far. - Events classified as
Responsesignal that the upload has been successfully finished.
By leveraging the UploadProgress events, we keep the current upload percentage updated in a member variable called uploadProgress, which is then used to refresh the progress bar's value.
Upon successful completion or failure of the upload, it is necessary to hide the progress bar from the user.
This is accomplished using the RxJS finalize operator, which ensures the reset() method is called in either scenario: success or failure.
Canceling an Upload in Progress
To support upload cancellation, we simply need to store a reference to the RxJS Subscription object resulting from subscribing to the http$ Observable.
In our component, this subscription is held in the uploadSub member variable.
If the user chooses to cancel while the upload is ongoing, they can click the cancel button. This triggers the cancelUpload() method, and the HTTP request is canceled by unsubscribing from the uploadSub subscription.
This unsubscription action immediately halts the current file upload process.
Restricting to Specific File Types
The final version of our file upload component can also mandate a specific file type by utilizing the requiredFileType property:
This property is subsequently bound to the accept attribute of the file input within the template. This forces the file selection dialog to only permit the user to choose a png file.
Uploading Multiple Files
By default, the browser's file dialog permits the selection of only one file.
However, by applying the multiple attribute, we can enable the user to select multiple files simultaneously:
Keep in mind that this scenario would require a fundamentally different UI than the one we've built. A single styled button with a progress bar is only appropriate for uploading one file.
For multiple file uploads, various UIs could be designed, such as a floating dialog displaying the progress of all active uploads.
Server-Side File Reception with Node
The method for handling the uploaded file depends on your backend technology. Here is a concise example of how to manage it with Node and the Express framework.
First, we must install the express-fileupload package. Then, we can register it as middleware in our Express application:
After that, all that's left is to define an Express route to handle the file upload requests:
Conclusion
The most effective strategy for handling file uploads in Angular is to develop one or more custom components tailored to your specific upload requirements.
A file upload component must internally include an HTML input of type file, which facilitates the user's file selection process.
This input should be hidden from view due to its lack of styleability, and substituted with a more user-friendly interface.
By using the file input in the background, we can access the selected file through the change event. This reference can then be used to construct and dispatch an HTTP request to the backend.
