transcend-io / conflux

Zip/unzip files of any size in the browser using streams.
MIT License
98 stars 15 forks source link
compression privacy streaming streams whatwg-streams

Table of Contents

Conflux by Transcend

Conflux

Build and read zip files with whatwg streams in the browser.

/ˈkänˌfləks/ (noun) a flowing together of two or more streams



Known Vulnerabilities


Blazing Fast

Compatibility

Chrome
Safari
Edge
Firefox

Examples

Usage

Importing Conflux

Package Manager

# With Yarn
yarn add @transcend-io/conflux

# With NPM
npm install --save @transcend-io/conflux
// Reader parses zip files, Writer builds zip files
import { Reader, Writer } from '@transcend-io/conflux';

CDN

<script src="https://cdn.jsdelivr.net/npm/@transcend-io/conflux@3"></script>
// Reader parses zip files, Writer builds zip files
const { Reader, Writer } = window.conflux;

Creating a ZIP

Example using ReadableStream#pipeThrough

import { Writer } from '@transcend-io/conflux';
import streamSaver from 'streamsaver';

const s3 = 'https://s3-us-west-2.amazonaws.com/bencmbrook/';
const files = ['NYT.txt', 'water.png', 'Earth.jpg'].values();

const myReadable = new ReadableStream({
  async pull(controller) {
    const { done, value } = files.next();
    if (done) return controller.close();
    const { body } = await fetch(s3 + value);
    return controller.enqueue({
      name: `/${value}`,
      stream: () => body,
    });
  },
});

myReadable
  .pipeThrough(new Writer())
  .pipeTo(streamSaver.createWriteStream('conflux.zip'));

Example using writer.write

import { Writer } from '@transcend-io/conflux';

import streamSaver from 'streamsaver';

// Set up conflux
const { readable, writable } = new Writer();
const writer = writable.getWriter();

// Set up streamsaver
const fileStream = streamSaver.createWriteStream('conflux.zip');

// Add a file
writer.write({
  name: '/cat.txt',
  lastModified: new Date(0),
  stream: () => new Response('mjau').body,
});

readable.pipeTo(fileStream);

writer.close();

Incorporating other streams

import { Writer } from '@transcend-io/conflux';
import streamSaver from 'streamsaver';

const { readable, writable } = new Writer();
const writer = writable.getWriter();
const reader = readable.getReader();

// Set up streamsaver
const fileStream = streamSaver.createWriteStream('conflux.zip');

(async () => {
  writer.write({
    name: '/cat.txt',
    lastModified: new Date(0),
    stream: () => new Response('mjau').body,
  });

  const imgStream = await fetch(
    'https://s3-us-west-2.amazonaws.com/bencmbrook/Earth.jpg',
  ).then((r) => r.body);

  writer.write({
    name: '/Earth.jpg',
    lastModified: new Date(0),
    stream: () => imgStream,
  });

  readable.pipeTo(fileStream);

  writer.close();
})();

Reading ZIP files

import { Reader } from '@transcend-io/conflux';

fetch('https://cdn.jsdelivr.net/gh/Stuk/jszip/test/ref/deflate.zip').then(
  async (res) => {
    const zip = await res.blob();
    for await (const entry of Reader(zip)) {
      console.log(entry);
    }
  },
);

Supporting Firefox

Firefox does not support ReadableStream#pipeThrough, since it does not have WritableStream or TransformStream support yet. Conflux ponyfills TransformStream out of the box in Firefox, but if you're using the myReadable.pipeThrough and plan to support Firefox, you'll want to ponyfill ReadableStream like so:

import { ReadableStream as ReadableStreamPonyfill } from 'web-streams-polyfill/ponyfill';

// Support Firefox with a ponyfill on ReadableStream to add .pipeThrough
const ModernReadableStream = window.WritableStream
  ? window.ReadableStream
  : ReadableStreamPonyfill;

const myReadable = new ModernReadableStream({
  async pull(controller) {
    return controller.enqueue({
      name: `/firefox.txt`,
      stream: () => new Response.body('Firefox works!'),
    });
  },
});

myReadable
  .pipeThrough(new Writer()) // see "Supporting Firefox" below
  .pipeTo(streamSaver.createWriteStream('conflux.zip'));

License

FOSSA Status