Running the sample application will give you the option to select an image with a file control. You can see the preview of the selected image before you start uploading it to the server. A progress control is also added so that you can see the upload progress in real-time.
The markup for the UI is pretty simple as,
I'm only concerned with a single upload that's why I passed the first file in the files array down to the onChange event.
Notice that there is no form element wrapped around the file input
The component class does nothing more interesting than reading the image using FileReader and setting the preview.
In this scenario, using Reactive Forms control only to check the validity of the attached file control is an overkill. That's why it is ignored.
What's interesting is the uploader service. Here's what it looks like:
You can send the raw file or wrap it into a FormData before sending it to the server side. It depends on your own implementation or the server-side framework you are working with. However, in most cases encrypting the file with FormData is considered the best practice.
To get the progress report of an HTTP request, you have to enable the flag for reportProgress. An ongoing HTTP request can emit a bunch of events and we can tap into those using the Rxjs tap operator. When the upload is finished the last value (HttpEventType.Response) is emitted to the subscriber (onUpload() function of user.component.ts). The subscriber then shows the value in a presentable way.
To update the progress bar in real time, I took the liberty to declare a BehaviorSubjcet named progressSource. This subject will get a new value every time an HttpEventType.UploadProgress event is emitted. This event contains the loaded and total property which is used in this scenario to find out the percentage of the uploaded file. I subscribed to this source in the ngOnInit hook of the component class.
And that's all about it. Fire up your own server and change the URL in the uploader service to your upload API endpoint.