Unzip files in React App

Code Snippet, using zip.js library:

import React, { useState, ChangeEvent } from "react";
import * as zip from "@zip.js/zip.js";

interface ZipEntry {
  name: string;
  size: number;
  entry: zip.Entry;
}

function PackagePage(): JSX.Element {
  const [files, setFiles] = useState<ZipEntry[]>([]);
  const [indexFile, setIndexFile] = useState<ZipEntry | null>(null);

  const handleFileChange = async (event: ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (file) {
      try {
        const zipReader = new zip.ZipReader(new zip.BlobReader(file));
        const entries = await zipReader.getEntries();
        const fileList: ZipEntry[] = entries.map((entry) => ({
          name: entry.filename,
          size: entry.uncompressedSize,
          entry: entry,
        }));
        setFiles(fileList);
        await zipReader.close();
      } catch (error) {
        console.error("Error reading zip file:", error);
        alert("Error reading zip file. Please try again.");
      }
    }
  };

  const handleIndexFileSelect = (event: ChangeEvent<HTMLSelectElement>) => {
    const selectedFile = files.find((file) => file.name === event.target.value);
    setIndexFile(selectedFile || null);
  };

  //TODO: Upload All the Files and Save the Index html File

  return (
    <div className="flex flex-col gap-4 max-w-full w-full bg-white h-fit min-h-screen text-black">
      <h2>Read a zip file (demo)</h2>
      <div>
        <label className="text-black flex flex-row gap-2 w-full">
          <span className="form-label">Choose a zip file</span>
          <input
            type="file"
            id="file-input"
            accept="application/zip"
            onChange={handleFileChange}
          />
        </label>
      </div>
      {files.length > 0 && (
        <div>
          <h3>Files in the ZIP archive:</h3>
          <ul>
            {files.map((file, index) => (
              <li key={index}>
                {file.name} - {file.size} bytes
              </li>
            ))}
          </ul>
          <div>
            <label className="text-black flex flex-row gap-2 w-full">
              <span className="form-label">Select index.html file:</span>
              <select onChange={handleIndexFileSelect}>
                <option value="">Select a file</option>
                {files
                  .filter((file) => file.name.endsWith(".html"))
                  .map((file, index) => (
                    <option key={index} value={file.name}>
                      {file.name}
                    </option>
                  ))}
              </select>
            </label>
          </div>
          {indexFile && (
            <div>
              <h4>Selected index file:</h4>
              <p>{indexFile.name}</p>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

export default PackagePage;

Did you find this article valuable?

Support Pratik Sharma by becoming a sponsor. Any amount is appreciated!