DEV Community

Lucas Damian Johnson
Lucas Damian Johnson

Posted on

Compress & Decompress An ArrayBuffer Client Side in JS

The Compressions Streams API is new and up and coming way to compress and decompress data in the browser. Please note the support for the API is not very wide so use at your own risk.

I am writing this because I did not find any good examples of just compressing/decompressing an ArrayBuffer which is what I needed the API to do. The following two code snippets show how to do exactly that.

Compress An Array Buffer

const compressArrayBuffer = async (input: ArrayBuffer) => {
  //create the stream
  const cs = new CompressionStream("gzip");
  //create the writer
  const writer = cs.writable.getWriter();
  //write the buffer to the writer 
  writer.write(input);
  writer.close();
  //create the output 
  const output: Uint8Array[] = [];
  const reader = cs.readable.getReader();
  let totalSize = 0;
  //go through each chunk and add it to the output
  while (true) {
    const { value, done } = await reader.read();
    if (done) break;
    output.push(value);
    totalSize += value.byteLength;
  }
  const concatenated = new Uint8Array(totalSize);
  let offset = 0;
  //finally build the compressed array and return it 
  for (const array of output) {
    concatenated.set(array, offset);
    offset += array.byteLength;
  }
  return concatenated;
};

Enter fullscreen mode Exit fullscreen mode

Deeompress An Array Buffer

const  decompressArrayBuffer = async (input: ArrayBuffer): Promise<Uint8Array> =>{
  //create the stream
  const ds = new DecompressionStream("gzip");
  //create the writer
  const writer = ds.writable.getWriter();
  //write the buffer to the writer thus decompressing it 
  writer.write(input);
  writer.close();
  //create the output
  const output: Uint8Array[] = [];
  //create the reader
  const reader = ds.readable.getReader();
  let totalSize = 0;
  //go through each chunk and add it to the output
  while (true) {
   const { value, done } = await reader.read();
   if (done) break;
   output.push(value);
   totalSize += value.byteLength;
  }
  const concatenated = new Uint8Array(totalSize);
  let offset = 0;
  //finally build the compressed array and return it 
  for (const array of output) {
   concatenated.set(array, offset);
   offset += array.byteLength;
  }
  return concatenated;
 }

Enter fullscreen mode Exit fullscreen mode

Top comments (4)

Collapse
 
shav profile image
A Sh

This can be simplified:

const ds = new DecompressionStream("gzip");
const writer = ds.writable.getWriter();
writer.write(input);
writer.close();
return new Response(ds.readable).arrayBuffer();
Enter fullscreen mode Exit fullscreen mode
Collapse
 
tohodo profile image
Tommy

This can be simplified some more: stackoverflow.com/a/75793593/452587

Collapse
 
linksake profile image
Luis Angel Ortega

This is great! Just what I needed, thanks for sharing!

Collapse
 
linksake profile image
Luis Angel Ortega

The code I ended up with:

const decompressBlob = async (blob) => {
    const ds = new DecompressionStream("gzip");
    const decompressedStream = blob.stream().pipeThrough(ds);
    const arrayBuffer = await new Response(decompressedStream).arrayBuffer();
    const int8Array = new Int8Array(arrayBuffer); 
    return Array.from(int8Array);
}
Enter fullscreen mode Exit fullscreen mode