mirror of
https://github.com/codedread/bitjs
synced 2025-10-04 01:59:15 +02:00
Start on issue #29: Add a Zipper that can take multiple files and produce a zip file as an array of bytes (storage only, no compression)
This commit is contained in:
parent
7389b71cf9
commit
c0afe7637e
5 changed files with 447 additions and 2 deletions
130
archive/compress.js
Normal file
130
archive/compress.js
Normal file
|
@ -0,0 +1,130 @@
|
|||
|
||||
import { ByteBuffer } from '../io/bytebuffer.js';
|
||||
|
||||
// NOTE: THIS IS A VERY HACKY WORK-IN-PROGRESS! THE API IS NOT FROZEN! USE AT YOUR OWN RISK!
|
||||
|
||||
/**
|
||||
* @typedef FileInfo An object that is sent to the worker to represent a file to zip.
|
||||
* @property {string} fileName The name of the file. TODO: Includes the path?
|
||||
* @property {number} lastModTime The number of ms since the Unix epoch (1970-01-01 at midnight).
|
||||
* @property {ArrayBuffer} fileData The bytes of the file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef CompressorOptions
|
||||
* @property {string} pathToBitJS A string indicating where the BitJS files are located.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @readonly
|
||||
* @enum {string}
|
||||
*/
|
||||
export const CompressStatus = {
|
||||
NOT_STARTED: 'not_started',
|
||||
READY: 'ready',
|
||||
WORKING: 'working',
|
||||
COMPLETE: 'complete',
|
||||
ERROR: 'error',
|
||||
};
|
||||
|
||||
/**
|
||||
* A thing that zips files.
|
||||
* NOTE: THIS IS A VERY HACKY WORK-IN-PROGRESS! THE API IS NOT FROZEN! USE AT YOUR OWN RISK!
|
||||
*/
|
||||
export class Zipper {
|
||||
/**
|
||||
* @param {CompressorOptions} options
|
||||
*/
|
||||
constructor(options) {
|
||||
/**
|
||||
* The path to the BitJS files.
|
||||
* @type {string}
|
||||
* @private
|
||||
*/
|
||||
this.pathToBitJS = options.pathToBitJS || '/';
|
||||
|
||||
/**
|
||||
* Private web worker initialized during start().
|
||||
* @type {Worker}
|
||||
* @private
|
||||
*/
|
||||
this.worker_ = null;
|
||||
|
||||
/**
|
||||
* @type {CompressStatus}
|
||||
* @private
|
||||
*/
|
||||
this.compressState = CompressStatus.NOT_STARTED;
|
||||
|
||||
/**
|
||||
* @type {Uint8Array}
|
||||
* @private
|
||||
*/
|
||||
this.byteArray = new Uint8Array(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Must only be called on a Zipper that has been started. See start().
|
||||
* @param {FileInfo[]} files
|
||||
* @param {boolean} isLastFile
|
||||
*/
|
||||
appendFiles(files, isLastFile) {
|
||||
if (!this.worker_) {
|
||||
throw `Worker not initialized. Did you forget to call start() ?`;
|
||||
}
|
||||
if (![CompressStatus.READY, CompressStatus.WORKING].includes(this.compressState)) {
|
||||
throw `Zipper not in the right state: ${this.compressState}`;
|
||||
}
|
||||
|
||||
this.worker_.postMessage({ files, isLastFile });
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {FileInfo[]} files
|
||||
* @param {boolean} isLastFile
|
||||
* @returns {Promise<Uint8Array>} A Promise that contains the entire zipped archive.
|
||||
*/
|
||||
start(files, isLastFile) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.worker_ = new Worker(this.pathToBitJS + `archive/zip.js`);
|
||||
this.worker_.onerror = (evt) => {
|
||||
console.log('Worker error: message = ' + evt.message);
|
||||
throw evt.message;
|
||||
};
|
||||
this.worker_.onmessage = (evt) => {
|
||||
if (typeof evt.data == 'string') {
|
||||
// Just log any strings the worker pumps our way.
|
||||
console.log(evt.data);
|
||||
} else {
|
||||
switch (evt.data.type) {
|
||||
case 'start':
|
||||
this.compressState = CompressStatus.WORKING;
|
||||
break;
|
||||
case 'finish':
|
||||
this.compressState = CompressStatus.COMPLETE;
|
||||
resolve(this.byteArray);
|
||||
break;
|
||||
case 'compress':
|
||||
this.addBytes_(evt.data.bytes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.compressState = CompressStatus.READY;
|
||||
this.appendFiles(files, isLastFile);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the internal byte array with new bytes (by allocating a new array and copying).
|
||||
* @param {Uint8Array} newBytes
|
||||
* @private
|
||||
*/
|
||||
addBytes_(newBytes) {
|
||||
const oldArray = this.byteArray;
|
||||
this.byteArray = new Uint8Array(oldArray.byteLength + newBytes.byteLength);
|
||||
this.byteArray.set(oldArray);
|
||||
this.byteArray.set(newBytes, oldArray.byteLength);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue