Add support for multiple layers of compression in the unpack client.

This commit is contained in:
Roger Far 2022-11-28 20:29:03 -07:00
parent f96ba0d20d
commit ee9ce2840b
2 changed files with 131 additions and 41 deletions

View file

@ -37,4 +37,40 @@ public static class FileHelper
}
}
}
public static async Task DeleteDirectory(String path)
{
if (String.IsNullOrWhiteSpace(path))
{
return;
}
if (!Directory.Exists(path))
{
return;
}
var retry = 0;
while (true)
{
try
{
Directory.Delete(path, true);
break;
}
catch
{
if (retry >= 3)
{
throw;
}
retry++;
await Task.Delay(1000 * retry);
}
}
}
}

View file

@ -74,50 +74,52 @@ public class UnpackClient
return;
}
await using (Stream stream = File.OpenRead(filePath))
var extractPath = _destinationPath;
String? extractPathTemp = null;
var archiveEntries = await GetArchiveFiles(filePath);
if (!archiveEntries.Any(m => m.StartsWith(_torrent.RdName + @"\")) && !archiveEntries.Any(m => m.StartsWith(_torrent.RdName + @"/")))
{
using var archive = RarArchive.Open(stream);
BytesTotal = archive.TotalSize;
var entries = archive.Entries.Where(entry => !entry.IsDirectory)
.ToList();
_rarfileStatus = entries.ToDictionary(entry => entry.Key, _ => 0L);
_rarCurrentEntry = null;
archive.CompressedBytesRead += ArchiveOnCompressedBytesRead;
var extractPath = _destinationPath;
if (!entries.Any(m => m.Key.StartsWith(_torrent.RdName + @"\")) && !entries.Any(m => m.Key.StartsWith(_torrent.RdName + @"/")))
{
extractPath = Path.Combine(_destinationPath, _torrent.RdName!);
}
if (entries.Any(m => m.Key.Contains(".r00")))
{
extractPath = Path.Combine(extractPath, "Temp");
}
foreach (var entry in entries)
{
if (_cancelled)
{
return;
}
_rarCurrentEntry = entry;
entry.WriteToDirectory(extractPath,
new ExtractionOptions
{
ExtractFullPath = true,
Overwrite = true
});
}
extractPath = Path.Combine(_destinationPath, _torrent.RdName!);
}
await FileHelper.Delete(filePath);
if (archiveEntries.Any(m => m.Contains(".r00")))
{
extractPathTemp = Path.Combine(extractPath, Guid.NewGuid().ToString());
if (!Directory.Exists(extractPathTemp))
{
Directory.CreateDirectory(extractPathTemp);
}
}
if (extractPathTemp != null)
{
Extract(filePath, extractPathTemp);
await FileHelper.Delete(filePath);
var rarFiles = Directory.GetFiles(extractPathTemp, "*.r00", SearchOption.TopDirectoryOnly);
foreach (var rarFile in rarFiles)
{
var mainRarFile = Path.ChangeExtension(rarFile, ".rar");
if (File.Exists(mainRarFile))
{
Extract(mainRarFile, extractPath);
}
await FileHelper.DeleteDirectory(extractPathTemp);
}
}
else
{
Extract(filePath, extractPath);
await FileHelper.Delete(filePath);
}
}
catch (Exception ex)
{
@ -129,6 +131,58 @@ public class UnpackClient
}
}
private async Task<IList<String>> GetArchiveFiles(String filePath)
{
await using Stream stream = File.OpenRead(filePath);
using var archive = RarArchive.Open(stream);
BytesTotal = archive.TotalSize;
var entries = archive.Entries
.Where(entry => !entry.IsDirectory)
.Select(m => m.Key)
.ToList();
return entries;
}
private void Extract(String filePath, String extractPath)
{
var parts = ArchiveFactory.GetFileParts(filePath);
using var archive = RarArchive.Open(parts.Select(m => new FileInfo(m)));
if (archive.IsComplete)
{
BytesTotal = archive.TotalSize;
}
var entries = archive.Entries.Where(entry => !entry.IsDirectory)
.ToList();
_rarfileStatus = entries.ToDictionary(entry => entry.Key, _ => 0L);
_rarCurrentEntry = null;
archive.CompressedBytesRead += ArchiveOnCompressedBytesRead;
foreach (var entry in entries)
{
if (_cancelled)
{
throw new Exception("Task was cancelled");
}
_rarCurrentEntry = entry;
entry.WriteToDirectory(extractPath,
new ExtractionOptions
{
ExtractFullPath = true,
Overwrite = true
});
}
}
private void ArchiveOnCompressedBytesRead(Object? sender, CompressedBytesReadEventArgs e)
{
if (_rarCurrentEntry == null)