Angular File Upload (With Upload Progress)
Sometimes you need to upload a file with the Angular framework.
And send it to a specific API server.
And while the file is being you want to track the progress of that upload and display the progress to the user.
Here's a straightforward guide to using Angular file input forms, uploading a file to a backend API and output the progress of the upload.
Step 1: Set Up the Angular File Input
Our first step is to use the HTML file input and bind it's change event.
<input type="file" (change)="onFileSelected($event)" />
And then we need to handle the file selection event inside our components Typescript file.
selectedFile: File | null = null;
onFileSelected(event: Event): void {
const input = event.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
this.selectedFile = input.files[0];
}
}
Step 2: Upload the File to the Backend API
Next we'll need to inject Angular's HttpClient and handle the HTTP request to our API.
import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';
constructor(private http: HttpClient) {}
Or if you prefer using the inject function.
import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';
const http = inject(HttpClient);
Now we'll define our upload method that checks if a file is selected. If selected it will use FormData
to upload it via our HTTP client.
uploadFile(): void {
if (!this.selectedFile) {
return;
}
const formData = new FormData();
formData.append('file', this.selectedFile);
this.http.post('https://api.blackhole.io/upload-file', formData).subscribe(
response => console.log('File uploaded successfully:', response),
error => console.error('File upload failed:', error)
);
}
And now we'll add a button in the HTML template to trigger the file upload.
<button (click)="uploadFile()">Upload File</button>
Step 3: Track the progress of the upload
Now we'll define a get event message method that we'll pipe the results of the upload results to monitor progress.
private getEventMessage(event: HttpEvent<any>) {
switch (event.type) {
case HttpEventType.UploadProgress:
const percentDone = event.total ? Math.round((100 * event.loaded) / event.total) : 0;
return percentDone;
case HttpEventType.Response:
return '100';
default:
return '';
}
}
And now we'll modify the upload call to report the progress.
uploadFile(): void {
if (!this.selectedFile) {
return;
}
const formData = new FormData();
formData.append('file', this.selectedFile);
const req = new HttpRequest('POST', 'https://api.blackhole.io/upload-file', formData, { reportProgress: true });
this.http.request(req)
.pipe(
map((progressEvent) => this.getEventMessage(progressEvent)),
tap((progress) => console.log(progress)),
last(),
)
.subscribe(
response => console.log('File uploaded successfully:', response),
error => console.error('File upload failed:', error)
);
}
Full Example Code
And here is our final code.
Our HTML template file.
<input type="file" (change)="onFileSelected($event)" />
<button (click)="uploadFile()">Upload File</button>
Along with the Typescript implementation.
import { Component } from '@angular/core';
import { HttpClient, HttpEvent, HttpEventType, HttpRequest } from '@angular/common/http';
import { last, map, tap } from 'rxjs';
@Component({
selector: 'app-file-upload',
templateUrl: './file-upload.component.html'
})
export class FileUploadComponent {
selectedFile: File | null = null;
constructor(private http: HttpClient) {}
onFileSelected(event: Event): void {
const input = event.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
this.selectedFile = input.files[0];
}
}
uploadFile(): void {
if (!this.selectedFile) {
return;
}
const formData = new FormData();
formData.append('file', this.selectedFile);
const req = new HttpRequest('POST', 'https://api.blackhole.io/upload-file', formData, { reportProgress: true });
this.http.request(req)
.pipe(
map((progressEvent) => this.getEventMessage(progressEvent)),
tap((progress) => console.log(progress)),
last(),
)
.subscribe(
response => console.log('File uploaded successfully:', response),
error => console.error('File upload failed:', error)
);
}
private getEventMessage(event: HttpEvent<any>) {
switch (event.type) {
case HttpEventType.UploadProgress:
const percentDone = event.total ? Math.round((100 * event.loaded) / event.total) : 0;
return percentDone;
case HttpEventType.Response:
return '100';
default:
return '';
}
}
}
And that, my friend, is how to upload a file with the Angular framework and track the progress.
Till next time,
Daniel Kreider