diff --git a/helpers/ArchiveHelper.ts b/helpers/ArchiveHelper.ts new file mode 100644 index 0000000000000000000000000000000000000000..61042990da04b1b7c88dd3144f3b6cf7843af48f --- /dev/null +++ b/helpers/ArchiveHelper.ts @@ -0,0 +1,69 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import tar from 'tar-stream'; +import stream from 'node:stream'; +import { Writable } from 'stream'; +import zlib from 'zlib'; + + +class ArchiveHelper { + private async explore(absoluteBasePath: string, rootPath: string, pack: tar.Pack) { + for ( let file of await fs.promises.readdir(rootPath) ) { + if ( file === 'output.tar' ) { + continue; + } + file = path.join(rootPath, file); + const stat = await fs.promises.stat(file); + if ( stat.isDirectory() ) { + await this.explore(absoluteBasePath, file, pack); + continue; + } + const entry = pack.entry({ + name: file.replace(absoluteBasePath, ''), + size: stat.size + }, (err) => { + if ( err ) { + throw err; + } + }); + const stream = fs.createReadStream(file); + stream.pipe(entry); + } + } + + private async compress(folderPath: string, tarDataStream: stream.Writable) { + const pack = tar.pack(); + + await this.explore(folderPath, folderPath, pack); + + pack.pipe(zlib.createGzip()).pipe(tarDataStream); + pack.finalize(); + } + + public async getBase64(folderPath: string): Promise<string> { + let data: any; + const tarDataStream = new stream.Writable({ + write(this: Writable, chunk: Buffer, _encoding: BufferEncoding, next: (error?: Error | null) => void) { + if ( data ) { + data += chunk.toString('hex'); + } else { + data = chunk.toString('hex'); + } + next(); + } + }); + + await this.compress(folderPath, tarDataStream); + + await (new Promise((resolve, reject) => { + tarDataStream.on('close', () => { + resolve(0); + }); + })); + + return Buffer.from(data, 'hex').toString('base64'); + } +} + + +export default new ArchiveHelper(); \ No newline at end of file