@@ -5,147 +5,125 @@ import { promiseWithResolver } from "octagonal-wheels/promises";
55 * A class to archive files
66 */
77export class Archiver {
8- _zipFile : fflate . Zip ;
9-
10- _aborted : boolean = false ;
11- _output : Uint8Array [ ] = [ ] ;
12-
13- _processedCount : number = 0 ;
14- _processedLength : number = 0 ;
15- _archivedCount : number = 0 ;
16- _archiveSize : number = 0 ;
17-
18-
19- progressReport ( type : string ) {
20- // console.warn(
21- // `Archiver: ${type} processed: ${this._processedCount} (${this._processedLength} bytes) ${this._archivedCount} (${this._archiveSize} bytes)`
22- // )
23- }
24-
25- _zipFilePromise = promiseWithResolver < Uint8Array > ( ) ;
26- get archivedZipFile ( ) : Promise < Uint8Array > {
27- return this . _zipFilePromise . promise ;
28- }
29-
30- get currentSize ( ) : number {
31- return this . _output . reduce ( ( acc , val ) => acc + val . length , 0 ) ;
32- }
33-
34- constructor ( ) {
35- // this._archiveName = archiveName;
36- const zipFile = new fflate . Zip ( async ( error , dat , final ) => this . _onProgress (
37- error , dat , final
38- ) ) ;
39- this . _zipFile = zipFile ;
40- }
41-
42- _onProgress ( err : fflate . FlateError | null , data : Uint8Array , final : boolean ) {
43- if ( err ) {
44- return this . _onError ( err ) ;
45- }
46- if ( data && data . length > 0 ) {
47- this . _output . push ( data ) ;
48- this . _archiveSize += data . length ;
49- }
50- // No error
51- this . progressReport ( "progress" ) ;
52- if ( this . _aborted ) {
53- return this . _onAborted ( ) ;
54- }
55- if ( final ) {
56- void this . _onFinalise ( ) ;
57- }
58- }
59-
60- async _onFinalise ( ) : Promise < void > {
61- this . _zipFile . terminate ( ) ;
62- const out = new Blob ( this . _output , { type : "application/zip" } ) ;
63- const result = new Uint8Array ( await out . arrayBuffer ( ) ) ;
64- this . _zipFilePromise . resolve ( result ) ;
65- }
66-
67- _onAborted ( ) {
68- this . _zipFile . terminate ( ) ;
69- this . _zipFilePromise . reject ( new Error ( "Aborted" ) ) ;
70- }
71- _onError ( err : fflate . FlateError ) : void {
72- this . _zipFile . terminate ( ) ;
73- this . _zipFilePromise . reject ( err ) ;
74- }
75-
76- addTextFile ( text : string , path : string , options ?: { mtime ?: number } ) : void {
77- const binary = new TextEncoder ( ) . encode ( text ) ;
78- this . addFile ( binary , path , options ) ;
79- }
80-
81- addFile ( file : Uint8Array , path : string , options ?: { mtime ?: number } ) : void {
82- const fflateFile = new fflate . ZipDeflate ( path , {
83- level : 9 ,
84- } ) ;
85- if ( options ?. mtime ) {
86- fflateFile . mtime = options . mtime ;
87- } else {
88- fflateFile . mtime = Date . now ( ) ;
89- }
90- this . _processedLength += file . length ;
91- this . progressReport ( "add" ) ;
92- this . _zipFile . add ( fflateFile ) ;
93-
94- // TODO: Check if the large file can be added in a single chunks
95- fflateFile . push ( file , true ) ;
96- }
97-
98- finalize ( ) {
99- this . _zipFile . end ( ) ;
100- return this . archivedZipFile ;
101- }
102-
103-
104-
105-
8+ _zipFile : fflate . Zip ;
9+ _aborted : boolean = false ;
10+ _output : Uint8Array [ ] = [ ] ;
11+ _processedCount : number = 0 ;
12+ _processedLength : number = 0 ;
13+ _archivedCount : number = 0 ;
14+ _archiveSize : number = 0 ;
15+
16+ progressReport ( type : string ) {
17+ // console.warn(
18+ // `Archiver: ${type} processed: ${this._processedCount} (${this._processedLength} bytes) ${this._archivedCount} (${this._archiveSize} bytes)`
19+ // )
20+ }
21+
22+ _zipFilePromise = promiseWithResolver < Uint8Array > ( ) ;
23+ get archivedZipFile ( ) : Promise < Uint8Array > {
24+ return this . _zipFilePromise . promise ;
25+ }
26+
27+ get currentSize ( ) : number {
28+ return this . _output . reduce ( ( acc , val ) => acc + val . length , 0 ) ;
29+ }
30+
31+ constructor ( ) {
32+ const zipFile = new fflate . Zip ( async ( error , dat , final ) => this . _onProgress ( error , dat , final ) ) ;
33+ this . _zipFile = zipFile ;
34+ }
35+
36+ _onProgress ( err : fflate . FlateError | null , data : Uint8Array , final : boolean ) {
37+ if ( err ) return this . _onError ( err ) ;
38+ if ( data && data . length > 0 ) {
39+ this . _output . push ( data ) ;
40+ this . _archiveSize += data . length ;
41+ }
42+ // No error
43+ this . progressReport ( "progress" ) ;
44+ if ( this . _aborted ) return this . _onAborted ( ) ;
45+ if ( final ) void this . _onFinalise ( ) ;
46+ }
47+
48+ async _onFinalise ( ) : Promise < void > {
49+ this . _zipFile . terminate ( ) ;
50+ const out = new Blob ( this . _output , { type : "application/zip" } ) ;
51+ const result = new Uint8Array ( await out . arrayBuffer ( ) ) ;
52+ this . _zipFilePromise . resolve ( result ) ;
53+ }
54+
55+ _onAborted ( ) {
56+ this . _zipFile . terminate ( ) ;
57+ this . _zipFilePromise . reject ( new Error ( "Aborted" ) ) ;
58+ }
59+
60+ _onError ( err : fflate . FlateError ) : void {
61+ this . _zipFile . terminate ( ) ;
62+ this . _zipFilePromise . reject ( err ) ;
63+ }
64+
65+ addTextFile ( text : string , path : string , options ?: { mtime ?: number } ) : void {
66+ const binary = new TextEncoder ( ) . encode ( text ) ;
67+ this . addFile ( binary , path , options ) ;
68+ }
69+
70+ addFile ( file : Uint8Array , path : string , options ?: { mtime ?: number } ) : void {
71+ const fflateFile = new fflate . ZipDeflate ( path , { level : 9 } ) ;
72+ fflateFile . mtime = options ?. mtime ?? Date . now ( ) ;
73+ this . _processedLength += file . length ;
74+ this . progressReport ( "add" ) ;
75+ this . _zipFile . add ( fflateFile ) ;
76+
77+ // TODO: Check if the large file can be added in a single chunks
78+ fflateFile . push ( file , true ) ;
79+ }
80+
81+ finalize ( ) {
82+ this . _zipFile . end ( ) ;
83+ return this . archivedZipFile ;
84+ }
10685}
10786
10887/**
10988 * A class to extract files from a zip archive
11089 */
11190export class Extractor {
112- _zipFile : fflate . Unzip ;
113- _isFileShouldBeExtracted : ( file : fflate . UnzipFile ) => boolean | Promise < boolean > ;
114- _onExtracted : ( filename : string , content : Uint8Array ) => Promise < void > ;
115- constructor ( isFileShouldBeExtracted : typeof this [ "_isFileShouldBeExtracted" ] , callback : typeof this [ "_onExtracted" ] , ) {
116- const unzipper = new fflate . Unzip ( ) ;
117- unzipper . register ( fflate . UnzipInflate ) ;
118- this . _zipFile = unzipper ;
119- this . _isFileShouldBeExtracted = isFileShouldBeExtracted ;
120- this . _onExtracted = callback ;
121- unzipper . onfile = async ( file : fflate . UnzipFile ) => {
122- if ( await this . _isFileShouldBeExtracted ( file ) ) {
123- const data : Uint8Array [ ] = [ ] ;
124- file . ondata = async ( err , dat , isFinal ) => {
125- if ( err ) {
126- console . error ( "Error extracting file" , err ) ;
127- return ;
128- }
129- if ( dat && dat . length > 0 ) {
130- data . push ( dat ) ;
131- }
132-
133- if ( isFinal ) {
134- const total = new Blob ( data , { type : "application/octet-stream" } ) ;
135- const result = new Uint8Array ( await total . arrayBuffer ( ) ) ;
136- await this . _onExtracted ( file . name , result ) ;
137- }
138- }
139- file . start ( ) ;
140- } else {
141- // Skip the file
142- }
143- }
144- }
145- addZippedContent ( data : Uint8Array , isFinal = false ) {
146- this . _zipFile . push ( data , isFinal ) ;
147- }
148- finalise ( ) {
149- this . _zipFile . push ( new Uint8Array ( ) , true ) ;
150- }
91+ _zipFile : fflate . Unzip ;
92+ _isFileShouldBeExtracted : ( file : fflate . UnzipFile ) => boolean | Promise < boolean > ;
93+ _onExtracted : ( filename : string , content : Uint8Array ) => Promise < void > ;
94+
95+ constructor ( isFileShouldBeExtracted : Extractor [ "_isFileShouldBeExtracted" ] , callback : Extractor [ "_onExtracted" ] ) {
96+ const unzipper = new fflate . Unzip ( ) ;
97+ unzipper . register ( fflate . UnzipInflate ) ;
98+ this . _zipFile = unzipper ;
99+ this . _isFileShouldBeExtracted = isFileShouldBeExtracted ;
100+ this . _onExtracted = callback ;
101+ unzipper . onfile = async ( file : fflate . UnzipFile ) => {
102+ if ( await this . _isFileShouldBeExtracted ( file ) ) {
103+ const data : Uint8Array [ ] = [ ] ;
104+ file . ondata = async ( err , dat , isFinal ) => {
105+ if ( err ) {
106+ console . error ( "Error extracting file" , err ) ;
107+ return ;
108+ }
109+ if ( dat && dat . length > 0 ) data . push ( dat ) ;
110+
111+ if ( isFinal ) {
112+ const total = new Blob ( data , { type : "application/octet-stream" } ) ;
113+ const result = new Uint8Array ( await total . arrayBuffer ( ) ) ;
114+ await this . _onExtracted ( file . name , result ) ;
115+ }
116+ } ;
117+ file . start ( ) ;
118+ }
119+ } ;
120+ }
121+
122+ addZippedContent ( data : Uint8Array , isFinal = false ) {
123+ this . _zipFile . push ( data , isFinal ) ;
124+ }
125+
126+ finalise ( ) {
127+ this . _zipFile . push ( new Uint8Array ( ) , true ) ;
128+ }
151129}
0 commit comments