Skip to content

Instantly share code, notes, and snippets.

@asidko
Created April 20, 2022 14:00
Show Gist options
  • Save asidko/9c7064027039411a11323eaf7d8ea2a4 to your computer and use it in GitHub Desktop.
Save asidko/9c7064027039411a11323eaf7d8ea2a4 to your computer and use it in GitHub Desktop.
Encode and decode base64 GZIP with pure JavaScript. Works in all modern browsers.
// Paste the following example to browser console
// Comppreses string to GZIP. Retruns a Promise with Base64 string
const compress = string => {
const blobToBase64 = blob => new Promise((resolve, _) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result.split(',')[1]);
reader.readAsDataURL(blob);
});
const byteArray = new TextEncoder().encode(string);
const cs = new CompressionStream('gzip');
const writer = cs.writable.getWriter();
writer.write(byteArray);
writer.close();
return new Response(cs.readable).blob().then(blobToBase64);
};
// Decompresses base64 encoded GZIP string. Retruns a string with original text.
const decompress = base64string => {
const bytes = Uint8Array.from(atob(base64string), c => c.charCodeAt(0));
const cs = new DecompressionStream('gzip');
const writer = cs.writable.getWriter();
writer.write(bytes);
writer.close();
return new Response(cs.readable).arrayBuffer().then(function (arrayBuffer) {
return new TextDecoder().decode(arrayBuffer);
});
}
/////////////////////
// Checking
/////////////////////
Promise.resolve("Hello GZIP!")
.then(v => {
console.log("Original value: %s", v);
return v;
})
.then(v => compress(v))
.then(v => {
console.log("Compressed value: %s", v);
return v;
})
.then(v => decompress(v))
.then(v => console.log("Decomporessed value: %s", v));
@A99US
Copy link

A99US commented Oct 15, 2024

Apologies for late re-reply. I just saw your answer after going thru my bookmarks.

I tried your codes and I don't know how to save the result into a var. Granted I'm still grasping on this whole Promise technique.

Anyway, this is the code that I've been using since I asked that question. It catches the error, but somehow the error is still on the console claiming that it's still uncatched. I don't know why this code works, but it works. Maybe you want to check it out. The error message is in writer.closed as far as I understand.

async function decomp(str,mode="gzip"){
  // Using Node Buffer for encoder
  str = Buffer.from(str, "base64")
  const cs = new DecompressionStream(mode)
  const writer = cs.writable.getWriter()
  writer.write(str)
  writer.close()
  return await new Response(cs.readable).arrayBuffer()
    .then(
      // Resolve Function
      arr=>(Buffer.from(arr)).toString("utf8"),
      // Reject Function
      async _=>{throw new Error(await Promise.reject(await writer.closed))}
    )
}

let string = [
  // "These strings were compressed!" compressed with gzip and base64 encoder
  `H4sIAAAAAAAACgvJSC1OVSguKcrMSy9WKE8tSlVIzs8tKEotLk5NUQQAfREzrR4AAAA`,
  // Change capital R near the end
  `H4sIAAAAAAAACgvJSC1OVSguKcrMSy9WKE8tSlVIzs8tKEotLk5NUQQAfREzrr4AAAA`,
  // Change 1 char at the end
  `H4sIAAAAAAAACgvJSC1OVSguKcrMSy9WKE8tSlVIzs8tKEotLk5NUQQAfREzrR4AAAx`,
  // Add 1 char at the end
  `H4sIAAAAAAAACgvJSC1OVSguKcrMSy9WKE8tSlVIzs8tKEotLk5NUQQAfREzrR4AAAAx`,
  ],
  result = []

console.clear()

for(let item of string){
  try{
    result.push(
      "Succesfully decompressing!\n\n" + "String Result : "+ (await decomp(item))
    )
  }
  catch(err){
    result.push("Failed to decompress!\n\n"+ err.name +" : "+ err.message)
  }
}

console.log(result.join("\n\n=====================================================================\n\n"))

Also an important question, is there a notification page somewhere in github? I just saw your reply. But I already subscribe to this post / gist. There must be notification somewhere, right?

Cheers

@davidnormo
Copy link

Thanks @asidko I was trying to roll my own version of this but ran into an error from the Response: "TypeError: Failed to fetch". I believe it was something to do with my approach to base64 encoding. Your implementation worked a treat 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment