Skip to content

Repository files navigation

zipup.js

Simple modern, small, zero dependency zip library for browser and node based JavaScript

Build and Deploy [Live Tests]

Most data is stored in blob so theoretically the browser or node can virtualize the storage.

Example Usage:

import { Zip } from '@greggman/zipup';

const zip = new Zip();
zip.addFile('foo.txt', someString);
zip.addFile('bar.png', someArrayBuffer);
zip.addFile('folder/moo.mp4', someArrayBufferView);
zip.addFile('folder/stuff.bin', someBlob);
const blob = await zip.finalize(comment?: string);

after which you could offer it to the user to download

const saveBlob = (function() {
  const a = document.createElement('a');
  document.body.appendChild(a);
  a.style.display = 'none';
  return function saveData(blob, fileName) {
    const url = window.URL.createObjectURL(blob);
    a.href = url;
    a.download = fileName;
    a.click();
  };
}());

saveBlob(blob, 'your-data.zip');

API

class Zip {
  constructor(options: { platform?: Platform });
  async addFile(pathOrInfo: string | EntryInfo, string | ArrayBuffer | ArrayBufferView | Blob): Promise<void>;
  addFolder(pathOrInfo: string | EntryInfo): ZipFolder;
  async finalize(comment?: string): Promise<Blob>;
};

class EntryInfo {
  name: string,                     // name of entry
  comment: string,                  // the comment for this entry
  lastModDate: Date,                // a Date
  attributes: number,               // platform specific attributes
};

class ZipFolder {
  async addFile(meta: string | EntryInfo, string | ArrayBuffer | ArrayBufferView | Blob): Promise<void>;
  addFolder(meta: string | EntryInfo): ZipFolder;  
};

type Platform = 'windows' | 'linux' | 'macos' | 'unix';

As you can see above you can pass either just a path, or an object with more meta data

zip.addFile('hello.txt', someString);
zip.addFile({
  name: 'readme.txt',
  comment?: 'the readme file',
  lastModData?: new Date(),  // or any date
}, content)

addFile is asynchronous. You do not have to wait as finalize will automatically wait but addFile does return a promise if you want to throttle (🤷‍♂️).

You can add a file to a folder either by including it in the name

zip.addFile('folder/file.bin', ...);

or by creating a folder

const folder = zip.addFolder('folder');
folder.addFile('file.bin');

Why?

Most of the other libraries are old and crufty. The browser itself now supports compression and so does node.js so why not just use those. Example: JSZip is 97k minified, 28k gzipped. zipup is 8k minified, 3k (gzipped). Yes, that's not a completely fair comparison. zipup has the functionality I need. I don't need the other stuff. Nor do I need 13 dependencies.

Note: the library uses CompressionStream. Use a polyfill if you're supporting old stuff.

Unzip

Use unzipit.

Attributes

AFAICT it's not common to use attributes in zip files. Attributes in zip files are platform specific and to be honest, I have no idea what all the various tools do as there are too many. Effectively, if you want to set permissions you should choose a platform when you create the zip file and then use the appropriate permissions.

import {Zip, DosAttributes, UnixPermissions} from 'zipup';

const dosZip = new Zip({platform: 'windows'});
dosZip.addFile({
  name: 'foo.txt',
  attributes: DosAttributes.READ_ONLY,
});
const dosBlob = await dosZip.finalize();

const unixZip = new Zip({platform: 'unix'});
unixZip.addFile({
  name: 'foo.txt',
  attributes: UnixPermissions.FILE_755, // or 0o755
});
const unixZip = await dosZip.finalize();

Testing

Use npm test to run the tests from the command line.

Live Browser Tests

https://greggman.github.io/zipup/test/

License

MIT

About

Simple modern, small, zero dependency zip library for browser and node based JavaScript

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages