Download Multiple Files as a .Zip File using Angular

Introduction 

 
This article helps you to download multiple files as a zip file using Angular and SharePoint Online.
 
Prerequisites
  1. Download and Install Node from Node
  2. Install and create an Angular project using Angular CLI from here: Angular CLI 
  3. Create a document library and upload the sample files in it.
To create the zip file in Angular, the way we were required to for the js zip library file.
  1. npm i jszip  
To save the file on the client-side, we are required to file-save the library file.
  1. npm i file-saver  
Create a component(FileDownloaderClient) in Angular for downloading the file on the client side.
  1. ng g c File/FileDownloaderClient  
Create a proxy for SharePoint online using my previous blog Proxy With Angular 6+ And SharePoint Environment.
 
To show the files in the browser, PrimeNG table has been used. To know more details about PrimeNG, refer here.
 
Now the file-downloader-client.component.html will look like the following:
  1. <p-table [value]="filesArray">  
  2.     <ng-template pTemplate="header">  
  3.         <tr>  
  4.             <th>Sr.No</th>  
  5.             <th>  
  6.                 File Name  
  7.             </th>  
  8.         </tr>  
  9.     </ng-template>  
  10.     <ng-template pTemplate="body" let-item let-rowIndex="rowIndex">  
  11.         <tr>  
  12.             <td>{{rowIndex + 1}}</td>  
  13.             <td>  
  14.                 <a href={{item.FileRef}}>{{item.FileLeafRef}}</a>  
  15.             </td>  
  16.         </tr>  
  17.     </ng-template>  
  18. </p-table>  
  19. <p-button label="Download" type="button" (click)="downloadFile()"></p-button>  
Import the install library in file-downloader-client.component.ts
  1. import * as JSZip from 'jszip';  
  2. import * as FileSaver from 'file-saver';  
The complete file-downloader-client.component.ts will look like:
  1. import { Component, OnInit } from '@angular/core';  
  2. import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';  
  3. import * as JSZip from 'jszip';  
  4. import * as FileSaver from 'file-saver';  
  5. import { TableModule } from 'primeng/table';  
  6. import { GlobalServicesService } from 'src/app/services/global-services.service';  
  7. @Component({  
  8.   selector: 'app-file-downloader-client',  
  9.   templateUrl: './file-downloader-client.component.html',  
  10.   styleUrls: ['./file-downloader-client.component.css']  
  11. })  
  12. export class FileDownloaderClientComponent implements OnInit {  
  13.   jsonHeader = 'application/json; odata=verbose';  
  14.   headersOld = new Headers({ 'Content-Type'this.jsonHeader, Accept: this.jsonHeader });  
  15.   headers = { 'Content-Type'this.jsonHeader, Accept: this.jsonHeader };  
  16.   filesArray: [];  
  17.   showFileArray: [];  
  18.   constructor(  
  19.     private httpClient: HttpClient,  
  20.     private globalService: GlobalServicesService  
  21.   ) { }  
  22.   ngOnInit() {  
  23.     this.getFilesFromLibrary();  
  24.   }  
  25.   async readFiles(listName: string, options?: any) {  
  26.     let res;  
  27.     const url = this.globalService.sharePointPageObject.webAbsoluteUrl + '/_api/web/lists/GetByTitle(\'' + listName + '\')/items?$select=FileRef,FileLeafRef';  
  28.     res = await this.httpClient.get(url, this.getHeaders(truetrue)).toPromise().catch((err: HttpErrorResponse) => {  
  29.       const error = err.error;  
  30.       return error;  
  31.     });  
  32.     return this.parseResults(res);  
  33.   }  
  34.   parseResults(res) {  
  35.     if (res) {  
  36.       if (res.hasOwnProperty('d') && res.d.hasOwnProperty('results')) {  
  37.         return res.d.results;  
  38.       } else if (res.hasOwnProperty('error')) {  
  39.         const obj: any = res.error;  
  40.         obj.hasError = true;  
  41.         return obj;  
  42.       } else {  
  43.         return {  
  44.           hasError: true,  
  45.           comments: res  
  46.         };  
  47.       }  
  48.     } else {  
  49.       return {  
  50.         hasError: true,  
  51.         comments: 'Check the response in network trace'  
  52.       };  
  53.     }  
  54.   }  
  55.   getHeaders(bAddContext, returnOp) {  
  56.     const headerCopy: any = Object.assign({}, this.headers);  
  57.     if (bAddContext) {  
  58.       const context: any = document.getElementById('__REQUESTDIGEST');  
  59.       if (context) {  
  60.         headerCopy['X-RequestDigest'] = context.value;  
  61.       }  
  62.     }  
  63.     if (returnOp) {  
  64.       const httpOptions = {  
  65.         headers: new HttpHeaders(headerCopy)  
  66.       };  
  67.       return httpOptions;  
  68.     } else {  
  69.       return headerCopy;  
  70.     }  
  71.   
  72.   }  
  73.   
  74.   async getFilesFromLibrary() {  
  75.     const results = await this.readFiles('Test_ABC');  
  76.     this.filesArray = results;  
  77.     console.log(results);  
  78.   }  
  79.   downloadFile() {  
  80.     this.createZip(this.filesArray.map(c => c.FileRef), 'Sample');  
  81.   }  
  82.   async getFile(url: string) {  
  83.     const httpOptions = {  
  84.       responseType: 'blob' as 'json'  
  85.     };  
  86.     const res = await this.httpClient.get(url, httpOptions).toPromise().catch((err: HttpErrorResponse) => {  
  87.       const error = err.error;  
  88.       return error;  
  89.     });  
  90.     return res;  
  91.   }  
  92.   async createZip(files: any[], zipName: string) {  
  93.     const zip = new JSZip();  
  94.     const name = zipName + '.zip';  
  95.     // tslint:disable-next-line:prefer-for-of  
  96.     for (let counter = 0; counter < files.length; counter++) {  
  97.       const element = files[counter];  
  98.       const fileData: any = await this.getFile(element);  
  99.       const b: any = new Blob([fileData], { type: '' + fileData.type + '' });  
  100.       zip.file(element.substring(element.lastIndexOf('/') + 1), b);  
  101.     }  
  102.     zip.generateAsync({ type: 'blob' }).then((content) => {  
  103.       if (content) {  
  104.         FileSaver.saveAs(content, name);  
  105.       }  
  106.     });  
  107.   }  
  108. }  
Now run npm run start in terminal and browse http://localhost:4200/#/fileDownload to view the file on the browser.
 
Click on the download button to download the file as a zip folder.
 
Please find the attached source code