Skip to content

Instantly share code, notes, and snippets.

@dungsaga
Forked from rvaiya/zip.js
Created July 1, 2023 09:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dungsaga/f3a0819e19fc899c9baf56611a0a6762 to your computer and use it in GitHub Desktop.
Save dungsaga/f3a0819e19fc899c9baf56611a0a6762 to your computer and use it in GitHub Desktop.
tinyzip.js - A tiny zip file generator in 70 lines of javascript.
// Author: Raheman Vaiya
// License: WTFPL
//
// A tiny zip generator in < 70 lines of javascript.
// Produces an uncompressed zip blob when fed an array
// of the form:
//
// [{name: 'filename', data: <Uint8Array>}]
//
// Useful for bookmarklets, don't use this in production :P.
//
// Less than 2% the size of minified jszip (without all the bells and whistles).
//
// Refs:
//
// https://en.wikipedia.org/wiki/ZIP_(file_format)
// https://gist.github.com/rvaiya/9b39813d74ce3d5e1412e6b813a29c3b#file-zip-implementation-go
function zip(files) {
// Generate the crc32 table instead of hardcoding it to avoid having a giant constant
// in the minified output...
const crc32_table = function() {
const tbl = [];
var c;
for(var n = 0; n < 256; n++){
c = n;
for(var k =0; k < 8; k++){
c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
}
tbl[n] = c;
}
return tbl;
}();
function crc32(arr) {
var crc = -1;
for(var i=0; i<arr.length; i++) {
crc = (crc >>> 8) ^ crc32_table[(crc ^ arr[i]) & 0xFF];
}
return (crc ^ (-1)) >>> 0;
}
function putUint32s(arr, offset, ...values) {
const dv = new DataView(arr.buffer);
values.forEach((v,i)=>dv.setUint32(offset+i*4, v, true));
}
function putUint16s(arr, offset, ...values) {
const dv = new DataView(arr.buffer);
values.forEach((v,i)=>dv.setUint16(offset+i*2, v, true));
}
const records = [];
const te = new TextEncoder('utf8');
var offset = 0;
var cdSz = 0;
files.forEach(file => {
const fh = new Uint8Array(30+file.name.length);
const fname = te.encode(file.name);
const chksum = crc32(file.data);
putUint32s(fh, 0, 0x04034b50);
putUint32s(fh, 14, chksum, file.data.length, file.data.length);
putUint16s(fh, 26, file.name.length);
fh.set(fname, 30);
file.header = fh;
file.offset = offset;
records.push(fh);
records.push(file.data);
//Create CD records pending flush at the end...
file.cdr = new Uint8Array(46+file.name.length);
putUint32s(file.cdr, 0, 0x02014b50);
putUint32s(file.cdr, 16, chksum, file.data.length, file.data.length);
putUint16s(file.cdr, 28, file.name.length);
putUint32s(file.cdr, 42, offset);
file.cdr.set(fname, 46);
cdSz += file.cdr.length;
offset += file.header.length + file.data.length;
});
//Push all accrued CD records..
files.forEach(f=>records.push(f.cdr));
//Add EOCD record...
const eocd = new Uint8Array(22);
putUint32s(eocd, 0, 0x06054b50);
putUint16s(eocd, 8, files.length, files.length);
putUint32s(eocd, 12, cdSz, offset);
records.push(eocd);
return new Blob(records, {type : 'application/zip'});
}
function zip(k){function f(a,b,...d){const c=new DataView(a.buffer);d.forEach((e,g)=>c.setUint32(b+4*g,e,!0))}function n(a,b,...d){const c=new DataView(a.buffer);d.forEach((e,g)=>c.setUint16(b+2*g,e,!0))}const q=function(){const a=[];for(var b,d=0;256>d;d++){b=d;for(var c=0;8>c;c++)b=b&1?3988292384^b>>>1:b>>>1;a[d]=b}return a}(),h=[],r=new TextEncoder("utf8");var l=0,p=0;k.forEach(a=>{const b=new Uint8Array(30+a.name.length),d=r.encode(a.name);var c=a.data;for(var e=-1,g=0;g<c.length;g++)e=e>>>8^
q[(e^c[g])&255];c=(e^-1)>>>0;f(b,0,67324752);f(b,14,c,a.data.length,a.data.length);n(b,26,a.name.length);b.set(d,30);a.header=b;a.offset=l;h.push(b);h.push(a.data);a.cdr=new Uint8Array(46+a.name.length);f(a.cdr,0,33639248);f(a.cdr,16,c,a.data.length,a.data.length);n(a.cdr,28,a.name.length);f(a.cdr,42,l);a.cdr.set(d,46);p+=a.cdr.length;l+=a.header.length+a.data.length});k.forEach(a=>h.push(a.cdr));const m=new Uint8Array(22);f(m,0,101010256);n(m,8,k.length,k.length);f(m,12,p,l);h.push(m);return new Blob(h,
{type:"application/zip"})};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment