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(true, true)).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. async getFilesFromLibrary() {
  73. const results = await this.readFiles('Test_ABC');
  74. this.filesArray = results;
  75. console.log(results);
  76. }
  77. downloadFile() {
  78. this.createZip(this.filesArray.map(c => c.FileRef), 'Sample');
  79. }
  80. async getFile(url: string) {
  81. const httpOptions = {
  82. responseType: 'blob' as 'json'
  83. };
  84. const res = await this.httpClient.get(url, httpOptions).toPromise().catch((err: HttpErrorResponse) => {
  85. const error = err.error;
  86. return error;
  87. });
  88. return res;
  89. }
  90. async createZip(files: any[], zipName: string) {
  91. const zip = new JSZip();
  92. const name = zipName + '.zip';
  93. // tslint:disable-next-line:prefer-for-of
  94. for (let counter = 0; counter < files.length; counter++) {
  95. const element = files[counter];
  96. const fileData: any = await this.getFile(element);
  97. const b: any = new Blob([fileData], { type: '' + fileData.type + '' });
  98. zip.file(element.substring(element.lastIndexOf('/') + 1), b);
  99. }
  100. zip.generateAsync({ type: 'blob' }).then((content) => {
  101. if (content) {
  102. FileSaver.saveAs(content, name);
  103. }
  104. });
  105. }
  106. }
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