Skip to content

Instantly share code, notes, and snippets.

@Explosion-Scratch
Created November 1, 2021 18:51
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Explosion-Scratch/357c2eebd8254f8ea5548b0e6ac7a61b to your computer and use it in GitHub Desktop.
Save Explosion-Scratch/357c2eebd8254f8ea5548b0e6ac7a61b to your computer and use it in GitHub Desktop.
Compress string using gzip and native browser APIs
function compress(string, encoding) {
const byteArray = new TextEncoder().encode(string);
const cs = new CompressionStream(encoding);
const writer = cs.writable.getWriter();
writer.write(byteArray);
writer.close();
return new Response(cs.readable).arrayBuffer();
}
function decompress(byteArray, encoding) {
const cs = new DecompressionStream(encoding);
const writer = cs.writable.getWriter();
writer.write(byteArray);
writer.close();
return new Response(cs.readable).arrayBuffer().then(function (arrayBuffer) {
return new TextDecoder().decode(arrayBuffer);
});
}
@PaperPrototype
Copy link

Thanks for this!

@Explosion-Scratch
Copy link
Author

Thanks for this!

No problem! This works well with a lot of the Web Crypto APIs

@USMortality
Copy link

USMortality commented Jun 13, 2023

Thx - Typescript version:

export const compress = async (
  str: string,
  encoding = 'gzip' as CompressionFormat
): Promise<ArrayBuffer> => {
  const byteArray = new TextEncoder().encode(str)
  const cs = new CompressionStream(encoding)
  const writer = cs.writable.getWriter()
  writer.write(byteArray)
  writer.close()
  return new Response(cs.readable).arrayBuffer()
}

export const decompress = async (
  byteArray: string[],
  encoding = 'gzip' as CompressionFormat
): Promise<string> => {
  const cs = new DecompressionStream(encoding)
  const writer = cs.writable.getWriter()
  writer.write(byteArray)
  writer.close()
  const arrayBuffer = await new Response(cs.readable).arrayBuffer()
  return new TextDecoder().decode(arrayBuffer)
}

@Explosion-Scratch
Copy link
Author

@USMortality nice

My TS version
const compress = (string: string, encoding: string): Promise<ArrayBuffer> => {
  const byteArray: Uint8Array = new TextEncoder().encode(string);
  const cs: CompressionStream = new CompressionStream(encoding);
  cs.writable.getWriter().write(byteArray).close();
  return new Response(cs.readable).arrayBuffer();
}

const decompress = (byteArray: Uint8Array, encoding: string): Promise<string> => {
  const cs: DecompressionStream = new DecompressionStream(encoding);
  cs.writable.getWriter().write(byteArray).close();
  return new Response(cs.readable).arrayBuffer().then((arrayBuffer: ArrayBuffer) => new TextDecoder().decode(arrayBuffer));
}

@BenChirlinn
Copy link

@Explosion-Scratch did you find a TS version that has CompressionStream defined? I can't find it in the latest release at all.

@USMortality
Copy link

USMortality commented Sep 1, 2023

Resolves for me in VS: https://developer.mozilla.org/en-US/docs/Web/API/CompressionStream
tsc -version: Version 5.1.6
Screenshot 2023-09-01 at 3 59 37 PM

@BenChirlinn
Copy link

BenChirlinn commented Sep 6, 2023

Ah confirmed that works. Looks like I need to try to bump our Typescript version which, sadly, might be a bit complicated. Thanks for your help!

@pengrui19930113
Copy link

thanks

@TCH68k
Copy link

TCH68k commented Sep 9, 2023

How this can be used from another function? I would like to gzip compress a string and get the result in a string. But all i get is a Promise and i cannot get the result out of it. No, await does not work. Even if i make the function async, all i get is a Promise.

function compress(string, encoding) {
  const byteArray = new TextEncoder().encode(string);
  const cs = new CompressionStream(encoding);
  const writer = cs.writable.getWriter();
  writer.write(byteArray);
  writer.close();
  return new Response(cs.readable).arrayBuffer();
}

async function wrapper(s)
{
	var x = compress(s, 'gzip').then
	(
		function (arrayBuffer)
		{
			return new TextDecoder().decode(arrayBuffer);
		}
	);
	var y = await x;
	return y;
}

var a = wrapper('Example string...');
console.log(a);

And it will get a Promise. I would like to use it synchronously.

@USMortality
Copy link

USMortality commented Sep 10, 2023

You should be able to use it like this:

const compressed = await(“hello world”, “utf-8”)
const decompressed = await decompress(compressed)

(Not tested; sent from my phone)

@TCH68k
Copy link

TCH68k commented Sep 11, 2023

Yep, works:

function compress(string, encoding) {
  const byteArray = new TextEncoder().encode(string);
  const cs = new CompressionStream(encoding);
  const writer = cs.writable.getWriter();
  writer.write(byteArray);
  writer.close();
  return new Response(cs.readable).arrayBuffer();
}

function promptDownload(filename, content, mimetype)
{
	if (mimetype === undefined)
	{
		mimetype = 'application/octet-stream';
	}

	var a = window.document.createElement('A');
	a.href = window.URL.createObjectURL(new Blob([content], {type: mimetype}));
	a.download = filename;
	document.body.appendChild(a);
	a.click();
	document.body.removeChild(a);
}

async function do_stuff()
{
	const s = "Árvíztűrő tükörfúrógép\n";
	var c = await compress(s + s + s + s + s + s + s + s, 'gzip');
	promptDownload('stuff.txt.gz', c);
}
do_stuff();

Thank you for the help and Explosion-Scratch for writing it.

@Explosion-Scratch
Copy link
Author

No problem @TCH68k - Happy to help, mention me if you want help with anything lol

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