If you want to open a local ZIP file, you need to install a software that supports ZIP decompression. But what if the pre-decompressed ZIP file is on the server? The simplest solution is to download the file locally and then unzip it using a zip-enabled decompression software. Is it possible to unzip the ZIP file online? The answer is yes. Next, We will introduce browser decompression and server decompression.

Before introducing the two options for extracting ZIP files online, let’s take a quick look at the ZIP file format.

Introduction to the ZIP format

The ZIP file format is a data compression and document storage file format, formerly known as Deflate, was invented by Phil Katz, who published the data in January 1989. ZIP usually uses the suffix “. ZIP “and its MIME format is” Application/ZIP “. Currently, ZIP is one of several mainstream compression formats, with competitors including RAR and the open source 7Z format.

ZIP is a fairly simple archive format that compresses each file separately, allowing individual files to be retrieved without having to read additional data. In theory, this format allows different algorithms to be used for different files. In practice, however, ZIP mostly uses Katz’s DEFLATE algorithm.

After a brief introduction to the ZIP format, the next brother will first introduce the browser decompression solution based on the JSZip library.

Pay attention to the “full stack of the road to repair the immortal” to read a baoge original 4 free e-books (accumulated downloads of 30 thousand +) and 11 Vue 3 advanced series tutorial.

Two, browser decompression scheme

JSZip is a JavaScript library for creating, reading, and editing.zip files. The library supports most browsers. The compatibility is shown below:

In fact, with the help of the JSZip library, it is not difficult to achieve the function of extracting ZIP files online on the browser side. Because we already have a complete example of unpacking a local file, unpacking a remote file, and generating a ZIP file. Ok, no more nonsense, let’s step by step to achieve online decompression ZIP file function.

2.1 Defining utility classes

The online ZIP file decompression function of the browser can be divided into three functions: downloading the ZIP file, parsing the ZIP file, and displaying the ZIP file. For functionality reusability, Apog encapsulates the logic for downloading and parsing ZIP files in the ExeJSZip class:

class ExeJSZip {
  // Used to obtain the file content corresponding to the URL address
  getBinaryContent(url, progressFn = () => {}) {
    return new Promise((resolve, reject) = > {
      if (typeofurl ! = ="string" || !/https? : /.test(url))
        reject(new Error("Url parameter is not valid"));
      JSZipUtils.getBinaryContent(url, { // JSZipUtils comes from the jszip-utils library
        progress: progressFn,
        callback: (err, data) = > {
          if (err) {
            reject(err);
          } else{ resolve(data); }}}); }); }// Traverse the Zip file
  async iterateZipFile(data, iterationFn) {
    if (typeofiterationFn ! = ="function") {
      throw new Error("IterationFn is not a function type");
    }
    let zip;
    try {
      zip = await JSZip.loadAsync(data); // JSZip comes from the JSZip library
      zip.forEach(iterationFn);
      return zip;
    } catch (error) {
      throw newerror(); }}}Copy the code

2.2 Decompressing the ZIP file online

Using an instance of the ExeJSZip class, we can easily decompress a ZIP file online:

The HTML code
<p>
  <label>Please enter the online address of the ZIP file:</label>
  <input type="text" id="zipUrl" />
</p>
<button id="unzipBtn" onclick="unzipOnline()">Online unzip</button>
<p id="status"></p>
<ul id="fileList"></ul>
Copy the code
JS code
const zipUrlEle = document.querySelector("#zipUrl");
const statusEle = document.querySelector("#status");
const fileList = document.querySelector("#fileList");
const exeJSZip = new ExeJSZip();

// Perform the online decompression operation
async function unzipOnline() {
  fileList.innerHTML = "";
  statusEle.innerText = "Start downloading files...";
  const data = await exeJSZip.getBinaryContent(
    zipUrlEle.value,
    handleProgress
  );
  let items = "";
  await exeJSZip.iterateZipFile(data, (relativePath, zipEntry) = > {
    items += `<li class=${zipEntry.dir ? "caret" : "indent"}>
      ${zipEntry.name}</li>`;
  });
  statusEle.innerText = "ZIP file decompressed successfully";
  fileList.innerHTML = items;
}

// Process the download progress
function handleProgress(progressData) {
  const { percent, loaded, total } = progressData;
  if (loaded === total) {
    statusEle.innerText = "The file has been downloaded. Try to unzip it."; }}Copy the code

The JSZip library is used to decompress ZIP files online in the browser. Let’s take a look at the example above:

Now that we can unzip the ZIP file online, some people may ask, can you preview the decompressed file? The answer is yes, because the JSZip library provides us with the File API through which we can read the contents of the specified file. For example, using zip.file(“amount.txt”).async(” arrayBuffer “), we can then perform the corresponding operation to implement the file preview function.

It is important to note that the JSzip-based scheme is not perfect and has some limitations. For example, it does not support decompression of encrypted ZIP files. When decompressing large files, the browser below IE 10 May appear flash exit problem. In addition, it has some other limitations, which I will not elaborate on here. If you are interested, you can read relevant content of Limitations of JSZip article.

Since browser unzipping solutions have some drawbacks, especially in the case of unzipping large files online, we can consider using server unzipping solutions to solve this problem.

3. Server decompression solution

The server decompression solution is to allow users to unzip files online using the file ID or file name. Next, We will introduce how to decompress zip files online on the server based on the koA and Node-stream-zip libraries. If you are not familiar with KOA, it is recommended that you read the official koA documentation first.

const path = require("path");
const Koa = require("koa");
const cors = require("@koa/cors");
const Router = require("@koa/router");
const StreamZip = require("node-stream-zip");

const app = new Koa();
const router = new Router();
const ZIP_HOME = path.join(__dirname, "zip"); // The root directory of the ZIP file
const UnzipCaches = new Map(a);// Save the decompressed file information

router.get("/".async (ctx) => {
  ctx.body = "Example of decompressing a ZIP file online on the server (Apogo)";
});

// Register the middleware
app.use(cors());
app.use(router.routes()).use(router.allowedMethods());

app.listen(3000.() = > {
  console.log("app starting at port 3000");
});
Copy the code

In the above code, we created a simple KOA application using the @KOA/CORS and @KOA/Router middleware. Based on the above code, let’s register a route to handle online decompression of the specified file name.

3.1 Decompress the SPECIFIED ZIP file according to the file name

app.js
router.get("/unzip/:name".async (ctx) => {
  const fileName = ctx.params.name;
  let filteredEntries;
  try {
    if (UnzipCaches.has(fileName)) { // Get it from cache first
      filteredEntries = UnzipCaches.get(fileName);
    } else {
      const zip = new StreamZip.async({ file: path.join(ZIP_HOME, fileName) });
      const entries = await zip.entries();
      filteredEntries = Object.values(entries).map((entry) = > {
        return {
          name: entry.name,
          size: entry.size,
          dir: entry.isDirectory,
        };
      });
      await zip.close();
      UnzipCaches.set(fileName, filteredEntries);
    }
    ctx.body = {
      status: "success".entries: filteredEntries,
    };
  } catch (error) {
    ctx.body = {
      status: "error".msg: 'Online decompression${fileName}File failure '}; }});Copy the code

In the above code, we get the final path of the file through ZIP_HOME and fileName, and then use the StreamZip object to perform the decompression operation. To avoid repeated decompression operations, Apolge defines an UnzipCaches cache object that holds information about decompressed files. With the above routes defined, let’s verify the functionality.

3.2 Decompress the ZIP file online

The HTML code
<p>
  <label>Please enter the ZIP file name:</label>
  <input type="text" id="fileName" value="kl_161828427993677" />
</p>
<button id="unzipBtn" onclick="unzipOnline()">Online unzip</button>
<p id="status"></p>
<ul id="fileList"></ul>
Copy the code
JS code
const fileList = document.querySelector("#fileList");
const fileNameEle = document.querySelector("#fileName");

const request = axios.create({
  baseURL: "http://localhost:3000/".timeout: 10000});async function unzipOnline() {
  const fileName = fileNameEle.value;
  if(! fileName)return;
  const response = await request.get(`unzip/${fileName}`);
  if (response.data && response.data.status === "success") {
    const entries = response.data.entries;
    let items = "";
    entries.forEach((zipEntry) = > {
      items += `<li class=${zipEntry.dir ? "caret" : "indent"}>${ zipEntry.name }</li>`; }); fileList.innerHTML = items; }}Copy the code

The result of the above example is shown in the figure below:

Now that we have decompressed the specified ZIP file according to the file name, can we preview the files in the specified path in the compressed file? Also can be the answer, using zip object provides entryData (entry: string | ZipEntry) : Promise < Buffer > method can read the contents of the directory specified file.

3.3 Previewing the ZIP file in the specified path

app.js
router.get("/unzip/:name/entry".async (ctx) => {
  const fileName = ctx.params.name; // ZIP file name
  const entryPath = ctx.query.path; // The path of the file
  try {
    const zip = new StreamZip.async({ file: path.join(ZIP_HOME, fileName) });
    const entryData = await zip.entryData(entryPath);
    await zip.close();
    ctx.body = {
      status: "success".entryData: entryData,
    };
  } catch (error) {
    ctx.body = {
      status: "error".msg: Read `${fileName}In the${entryPath}File failure '}; }});Copy the code

In the above code, we read the contents of the file at the specified path through the zip.entryData method, which returns a Buffer object. When the current end receives the data, it also needs to convert the received Buffer object into an ArrayBuffer object. The corresponding processing method is as follows:

function toArrayBuffer(buf) {
  let ab = new ArrayBuffer(buf.length);
  let view = new Uint8Array(ab);
  for (let i = 0; i < buf.length; ++i) {
    view[i] = buf[i];
  }
  return ab;
}
Copy the code

After defining the toArrayBuffer function, we can implement the preview function by calling the API defined by app.js. The code is as follows:

async function previewZipFile(path) {
  const fileName = fileNameEle.value; // Get the file name
  const response = await request.get(
    `unzip/${fileName}/entry? path=${path}`
  );
  if (response.data && response.data.status === "success") {
    const { entryData } = response.data;
    const entryBuffer = toArrayBuffer(entryData.data);
    const blob = new Blob([entryBuffer]);
    // Read the file information using url.createObjecturl or blob.text()}}Copy the code

Because the complete sample code content is more, a baoge does not put the specific code. Interested partners, can visit the following address to browse the sample code.

Gist.github.com/semlinker/3…

Note: The above code is for reference only, please adjust according to the actual business.

Four,

This article introduces two schemes to decompress the ZIP file online. In the actual project, it is recommended to use the server decompression scheme. This can not only solve the compatibility problem of the browser, but also can solve the problem of online decompression of large files, but also facilitate the later extension support other compression formats.

Pay attention to the “full stack of the road to repair the immortal” to read a baoge original 4 free e-books (accumulated downloads of 30 thousand +) and 11 Vue 3 advanced series tutorial. If you want to learn TS/Vue 3.0 together, you can add Semlinker on wechat.

5. Reference Resources

  • Wikipedia ZIP format
  • Limitations of JSZip