feat(tartools): add streaming TAR support (tar-stream), Node.js streaming APIs for TarTools, and browser / web bundle docs
This commit is contained in:
@@ -380,36 +380,41 @@ export class SmartArchive {
|
||||
plugins.smartstream.createTransformFunction<IAnalyzedResult, void>(
|
||||
async (analyzedResultChunk) => {
|
||||
if (analyzedResultChunk.fileType?.mime === 'application/x-tar') {
|
||||
// Use modern-tar for TAR extraction
|
||||
const chunks: Buffer[] = [];
|
||||
// Use tar-stream for streaming TAR extraction
|
||||
// Buffer each entry to ensure tar-stream can proceed to next entry
|
||||
const extract = this.tarTools.getExtractStream();
|
||||
|
||||
analyzedResultChunk.resultStream.on('data', (chunk: Buffer) => {
|
||||
chunks.push(chunk);
|
||||
});
|
||||
|
||||
analyzedResultChunk.resultStream.on('end', async () => {
|
||||
try {
|
||||
const tarBuffer = Buffer.concat(chunks);
|
||||
const entries = await this.tarTools.extractTar(new Uint8Array(tarBuffer));
|
||||
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory) continue;
|
||||
|
||||
const streamFile = plugins.smartfile.StreamFile.fromBuffer(
|
||||
Buffer.from(entry.content)
|
||||
);
|
||||
streamFile.relativeFilePath = entry.path;
|
||||
streamFileIntake.push(streamFile);
|
||||
}
|
||||
safeSignalEnd();
|
||||
} catch (err) {
|
||||
streamFileIntake.emit('error', err);
|
||||
extract.on('entry', (header, stream, next) => {
|
||||
if (header.type === 'directory') {
|
||||
stream.resume(); // Drain the stream
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
// Buffer the entry content to avoid blocking tar-stream
|
||||
const chunks: Buffer[] = [];
|
||||
stream.on('data', (chunk: Buffer) => chunks.push(chunk));
|
||||
stream.on('end', () => {
|
||||
const content = Buffer.concat(chunks);
|
||||
const streamFile = plugins.smartfile.StreamFile.fromBuffer(content);
|
||||
streamFile.relativeFilePath = header.name;
|
||||
streamFileIntake.push(streamFile);
|
||||
next();
|
||||
});
|
||||
stream.on('error', (err: Error) => {
|
||||
streamFileIntake.emit('error', err);
|
||||
});
|
||||
});
|
||||
|
||||
analyzedResultChunk.resultStream.on('error', (err: Error) => {
|
||||
extract.on('finish', () => {
|
||||
safeSignalEnd();
|
||||
});
|
||||
|
||||
extract.on('error', (err: Error) => {
|
||||
streamFileIntake.emit('error', err);
|
||||
});
|
||||
|
||||
analyzedResultChunk.resultStream.pipe(extract);
|
||||
} else if (analyzedResultChunk.fileType?.mime === 'application/zip') {
|
||||
analyzedResultChunk.resultStream
|
||||
.pipe(analyzedResultChunk.decompressionStream)
|
||||
|
||||
Reference in New Issue
Block a user