Utilize the JSZip library to compress files in Angular 11

I need to compress multiple txt files into a zip archive that are received in base64 format from a service response.

Here is the code snippet to download the zip file containing the compressed txt files stored under the "txt" folder:

let zip = new JSZip();
zip.file("readme.txt", "Description content");
let txtFile = zip.folder("txt");
this.selectedItems?.forEach((item) => {
    this.downloadService
    .downloadFile(item.name)
    .subscribe((response) => {
      let base64 = response.output.split(",");
      txtFile.file(item.name, base64[1], {base64: true});
    });
});
zip.generateAsync({type:"blob"})
.then(function(content) {
  // see FileSaver.js
  FileSaver.saveAs(content, "fileTxt.zip");
});

"selectedItems": represents an array of objects with various files, which are then compressed within the "txt" folder of the zip file. The property "item.name" refers to the file name within the array of objects.

I have encountered two issues:

1. Dynamic naming for the zip file

I am trying to assign a dynamic name to the zip file by storing it in a class attribute named "fileZipName" (the value of fileZipName is assigned during the onInit event of the component).

  zip.generateAsync({type:"blob"})
  .then(function(content) {
      // see FileSaver.js
      FileSaver.saveAs(content, this.fileZipName);
  });

However, when using the variable "fileZipName" within the "then" block, I encounter the following error in the browser console:

core.js:6210 ERROR Error: Uncaught (in promise): TypeError: Cannot read properties of undefined (reading 'fileZipName')
TypeError: Cannot read properties of undefined (reading 'fileZipName')

2. Adding files to the zip archive

When I provide a fixed name like "filesTxt.zip", everything works fine. The zip file is generated correctly with the "readme.txt" file included and the "txt" folder created. However, the problem arises as the "txt" folder appears empty without the expected compressed file inside.

The variable "base64[1]" contains the base64 encoding of the txt file: "VGVzdCBJbmZyYTEw". Decoding it online reveals the correct txt file contents.

No error messages are displayed.

Can anyone assist me with these issues? Thank you,

Answer №1

To tackle the initial issue, my suggestion is to delve into JavaScript context to grasp the problem at hand. To resolve the issue, simply swap out the traditional function expression for an arrow function expression. Here's the transformation:

Original Code

zip.generateAsync({type:"blob"})
  .then(function(content) {
    // see FileSaver.js
    FileSaver.saveAs(content, this.fileZipName);
});

Updated Code

zip.generateAsync({type:"blob"})
  .then((content) => {
    // see FileSaver.js
    FileSaver.saveAs(content, this.fileZipName);
});

In the former expression, the this keyword points to a different reference (leading to an undefined value), whereas in the latter, it correctly references the class instance.

Regarding the second issue, while I haven't personally worked with JSZip, based on the documentation, it seems that the folder function merely establishes a folder within the output zip. To incorporate subfiles within said folder, manual addition is required.

let zip = new JSZip();
zip.file("readme.txt", "Description content");

// Option 1 (adding files individually)
let txtFile = zip.folder("txt").file('file1.txt').file('file2.txt');
// Option 2 (adding all subfiles without discrimination) - Not tested
let txtFile = zip.folder("txt").file(/.*/);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The getCookie method has not been implemented in the DominoAdapter

When attempting to run Angular Universal on node, I encountered the following error message: ERROR Error: This method is not implemented in DominoAdapter: getCookie The issue seems to be stemming from the line in the server.js file: var domino = __w ...

What is the best way to implement debouncing for an editor value that is controlled by the parent component?

Custom Editor Component import Editor from '@monaco-editor/react'; import { useDebounce } from './useDebounce'; import { useEffect, useState } from 'react'; type Props = { code: string; onChange: (code: string) => void ...

Display the service reply within an array

I have received the following service response in Postman. I have created a service to retrieve this response for my Angular app. Here is my service: getSessions() { return this.http.get( 'http://127.0.0.1:8000/api/sessions/all/', { ...

How to fix the "Module parse failed" issue when importing MP3 files in NextJS 14 TypeScript?

Starting a new NextJS project, I used the command npx create-next-app@latest. Within this project, I created a simple TSX component that takes an imported MP3 file as a prop. 'use client'; import Image from "next/image"; import audioI ...

Angular 14 encountered an unexpected issue: There was an unhandled exception with the script file node_modules/tinymce/themes/modern/theme.min.js missing

After attempting to run ng serve, an error message appears: ⠋ Generating browser application bundles (phase: setup) ...An unhandled exception occurred: Script file node_modules/tinymce/themes/modern/theme.min.js does not exist. ⠋ Generating browser ap ...

Updating content in Angular 2 using PUT method with the "uri/list" content type for multiple elements

What is the process for sending multiple elements in a PUT request using Angular 2 and Typescript? In order to send multiple URIs, they must be separated by a line break: curl -i -X PUT -H "Content-Type:text/uri-list" --data-binary @uris.txt http://loc ...

Trouble with displaying cell content in ag-grid within an Angular application

I have implemented ag-grid in my Angular project and I am trying to redirect to a link when a specific cell is clicked. Currently, I have a new value coming from an API which is nested inside an object in an array. For example, the object is dto-> dat ...

Using Angular2 RC5 to share components across different modules

I'm currently in the process of updating my angular2-app to the latest version RC5. So far, everything is going smoothly, but I am now looking to restructure it using NgModules. However, I have encountered a slight issue: I have been using a componen ...

changing the breadcrumb item to a dropdown item in a dynamic way

Hey there, I'm currently working on creating a breadcrumb item using Angular. Here is what I have so far: https://i.stack.imgur.com/zt5yX.png I decided to add a dropdown for the breadcrumb item, but I'm facing a challenge: I want to be able to ...

Utilizing Anglar 16's MatTable trackBy feature on FormGroup for identifying unaltered fields

In my application, I am working with a MatTable that has a datasource consisting of AbstractControls (FormGroups) to create an editable table. At the end of each row, there are action buttons for saving or deleting the elements. My goal is to implement tr ...

Angular 2 - Component Loading Screen

I'm looking for a solution for my loading component that shows a spinner and retrieves a remote configuration file necessary for the app to work. Is there a way to have all routes pass through the loading component first to ensure the config data is l ...

How can you create an interface where the value type is determined by the key, but not all keys are predefined?

Below is an illustration of a data structure that I aim to define as a type in TypeScript: const dataExample = { Folder: { "Filename.js": { lines: { total: 100, covered: 80, ...

Exploring the methods of connecting with data-checked and data-unchecked attributes in Angular

Utilizing a toggle switch, I am able to determine what text to display in the div by utilizing html attributes such as data-checked and data-unchecked. In addition, I have an Angular pipe that translates all texts on the website based on the selected lang ...

Importing TweenLite in Typescript is a breeze

After downloading the GSAP package via npm, I am keen on importing the TweenLite class to my TypeScript app. While importing all of GSAP can be achieved by using require('gsap'); and it functions correctly, this method does not work in TypeScript ...

Prevent keyboard overlay during TextField interaction in a NativeScript app

When dealing with a NativeScript app view that includes a TextField component for user input, the native Keyboard Input tends to overlay the text field. Although it does not prevent users from entering text, it disrupts the overall user experience and affe ...

Encountering a 404 error when attempting to import the Angular 2 testing components ComponentFixture and TestBed

When I attempt to run my jasmine tests using a spec runner HTML file, I encounter this error: zone.js:1382 GET http://localhost:3002/node_modules/@angular/core/bundles/core.umd.js/testing 404 (Not Found) zone.js:232 Error: (SystemJS) XHR error (404 N ...

Parsing of the module has failed due to the presence of an unexpected character '' while attempting to import a video file

Trying to create a video player in NextJS using TS. I brought in a video file from my src/assets folder and encountered an error. Error - ./src/assets/video.mp4 Module parse failed: Unexpected character '' (1:0) You may need an appropriate load ...

Initiating a GET request to execute an SQL query with specified parameters

Let me provide some background information. I am currently using Angular for the frontend and Express for the backend, while also learning how to effectively utilize both technologies. In my application, there is a parent component that generates a group ...

What is the process of assigning a value type to a generic key type of an object in typescript?

I am currently working on developing a function that can merge and sort pre-sorted arrays into one single sorted array. This function takes an array of arrays containing objects, along with a specified key for comparison purposes. It is important to ensure ...

Is there a way to retrieve keys of the object from this combination type?

Can someone please help me understand how to retrieve keys from this union type? The Value is currently being assigned as a never type. I would like the Value to be either sno, key, or id type Key = { sno: number } | { key: number } | { id: number }; typ ...