In the previous tutorial, we discussed the file upload from a Angular Client to a Spring Boot back-end server. Most uploaded files on web are images. It’s always wise to compress and minify before sending them to the server. In this tutorial we will see how to Angular compress image before upload to Spring Boot back-end.
Table of contents
Install NPM libraries
ng2-file-select
As for the previous tutorial, we will use the same ng2-file-upload for file uploading. So install it :
1 |
npm i ng2-file-upload --save |
image-compressor.js
For image compression, we will use image-compressor.js. Install it using npm :
1 |
npm i image-compressor.js --save |
Once the library is installed, you need to add script in your application. If you are using Angular-CLI (which I highly recommend), add the script relative path to your angular.json like below :
1 2 3 4 5 6 |
"styles": [ "src/styles.scss" ], "scripts": [ "node_modules/image-compressor.js/dist/image-compressor.min.js" ] |
Libraries are now installed, let’s now see the Angular part.
Angular
ImgCompressor directive
To compress the image, we will extend the ng2-file-upload directive and add our compression there. Below the implementation :
- img-compressor.directive.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
import {Directive, ElementRef, NgZone} from '@angular/core'; import {FileSelectDirective} from 'ng2-file-upload'; declare var ImageCompressor: any; const compressor = new ImageCompressor(); @Directive({ selector: '[appImgCompressor]' }) export class ImgCompressorDirective extends FileSelectDirective { constructor(private zone: NgZone, private elementRef: ElementRef) { super(elementRef); } onChange(): any { // Retrieve the selected files. const files: FileList = this.element.nativeElement.files; this.zone.runOutsideAngular(() => { const promises: Promise<Blob>[] = []; // Compress each file and preserve a quality of 50%. for (let i = 0; i < files.length; ++i) { const file = files[i]; promises.push(compressor.compress(file, {quality: .5})); } // When all promises resolve, then upload files to server. Promise.all(promises).then(_files => this.uploadFile(_files)); }); } protected uploadFile(files: any[]) { this.uploader.addToQueue(files, this.getOptions(), this.getFilters()); this.onFileSelected.emit(files); if (!this.isEmptyAfterSelection()) { return; } } } |
Don’t forget to add the directive in the declarations of your @NgModule.
Component template
The template is a basic input using the appImgCompressor directive and an uploader.
- app.component.html
1 2 3 4 5 |
<h1>Roufid image compressor tutorial</h1> <div> <input type="file" appImgCompressor [uploader]="uploader"/> </div> |
Component
- app.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import {Component, OnInit} from '@angular/core'; import {FileUploader} from 'ng2-file-upload'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent implements OnInit { uploader: FileUploader; ngOnInit(): void { this.uploader = new FileUploader({url: 'api/files', autoUpload: true}); } } |
The tutorial source code is available on Github. Download the source