mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-07-09 02:26:47 +00:00
127 lines
4.5 KiB
C#
127 lines
4.5 KiB
C#
using System;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using SharpCompress.Common;
|
|
using SharpCompress.Readers;
|
|
|
|
namespace SharpCompress.Archives;
|
|
|
|
public static class IAsyncArchiveExtensions
|
|
{
|
|
extension(IAsyncArchive archive)
|
|
{
|
|
/// <summary>
|
|
/// Extract to specific directory asynchronously with progress reporting and cancellation support
|
|
/// </summary>
|
|
/// <param name="destinationDirectory">The folder to extract into.</param>
|
|
/// <param name="options">Extraction options.</param>
|
|
/// <param name="progress">Optional progress reporter for tracking extraction progress.</param>
|
|
/// <param name="cancellationToken">Optional cancellation token.</param>
|
|
public async ValueTask WriteToDirectoryAsync(
|
|
string destinationDirectory,
|
|
ExtractionOptions? options = null,
|
|
IProgress<ProgressReport>? progress = null,
|
|
CancellationToken cancellationToken = default
|
|
)
|
|
{
|
|
if (
|
|
await archive.IsSolidAsync().ConfigureAwait(false)
|
|
|| archive.Type == ArchiveType.SevenZip
|
|
)
|
|
{
|
|
var totalBytes = await archive.TotalUncompressedSizeAsync().ConfigureAwait(false);
|
|
var bytesRead = 0L;
|
|
await using var reader = await archive
|
|
.ExtractAllEntriesAsync()
|
|
.ConfigureAwait(false);
|
|
while (await reader.MoveToNextEntryAsync(cancellationToken).ConfigureAwait(false))
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
await reader
|
|
.WriteEntryToDirectoryAsync(
|
|
destinationDirectory,
|
|
options,
|
|
cancellationToken
|
|
)
|
|
.ConfigureAwait(false);
|
|
|
|
if (reader.Entry.IsDirectory)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
bytesRead += reader.Entry.Size;
|
|
progress?.Report(
|
|
new ProgressReport(reader.Entry.Key ?? string.Empty, bytesRead, totalBytes)
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
await archive
|
|
.WriteToDirectoryAsyncInternal(
|
|
destinationDirectory,
|
|
options,
|
|
progress,
|
|
cancellationToken
|
|
)
|
|
.ConfigureAwait(false);
|
|
}
|
|
}
|
|
|
|
private async ValueTask WriteToDirectoryAsyncInternal(
|
|
string destinationDirectory,
|
|
ExtractionOptions? options,
|
|
IProgress<ProgressReport>? progress,
|
|
CancellationToken cancellationToken
|
|
)
|
|
{
|
|
options ??= new ExtractionOptions();
|
|
var fullDestinationDirectoryPath = DirectoryManagement.GetFullDestinationDirectoryPath(
|
|
destinationDirectory
|
|
);
|
|
|
|
var totalBytes = await archive.TotalUncompressedSizeAsync().ConfigureAwait(false);
|
|
var bytesRead = 0L;
|
|
|
|
await foreach (
|
|
var entry in archive
|
|
.EntriesAsync.WithCancellation(cancellationToken)
|
|
.ConfigureAwait(false)
|
|
)
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
if (entry.IsDirectory)
|
|
{
|
|
await entry
|
|
.WriteEntryToDirectoryAsyncCore(
|
|
fullDestinationDirectoryPath,
|
|
options,
|
|
null,
|
|
cancellationToken
|
|
)
|
|
.ConfigureAwait(false);
|
|
continue;
|
|
}
|
|
|
|
await entry
|
|
.WriteEntryToDirectoryAsyncCore(
|
|
fullDestinationDirectoryPath,
|
|
options,
|
|
async (path, ct) =>
|
|
await entry.WriteToFileAsync(path, options, ct).ConfigureAwait(false),
|
|
cancellationToken
|
|
)
|
|
.ConfigureAwait(false);
|
|
|
|
bytesRead += entry.Size;
|
|
progress?.Report(
|
|
new ProgressReport(entry.Key ?? string.Empty, bytesRead, totalBytes)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|