Added the previous downloader back in, keep the Bezzad downloader in as a secondary.
This commit is contained in:
parent
c95f0171f7
commit
6c47ebcfad
6 changed files with 232 additions and 76 deletions
12
README.md
12
README.md
|
|
@ -145,10 +145,20 @@ If you use Proxmox for your homelab, you can run rdt-client in a linux container
|
||||||
|
|
||||||
### Download Clients
|
### Download Clients
|
||||||
|
|
||||||
Currently there 2 available download clients:
|
Currently there 4 available download clients:
|
||||||
|
|
||||||
#### Internal Downloader
|
#### Internal Downloader
|
||||||
|
|
||||||
|
This experimental [downloader](https://github.com/rogerfar/Downloader.NET) can be used to download files with multiple sections in parallel.
|
||||||
|
|
||||||
|
It has the following options:
|
||||||
|
|
||||||
|
- Download speed (in MB/s): This number indicates the speed in MB/s per download over all parallel downloads and chunks.
|
||||||
|
- Parallel connections per download: When a file is downloaded it is split in sections, this setting indicates how many sections you will download in parallel.
|
||||||
|
- Connection Timeout: This number indicates the timeout in milliseconds before a download chunk times out. It will retry each chunk 5 times before completely failing.
|
||||||
|
|
||||||
|
#### Bezzad Downloader
|
||||||
|
|
||||||
This [downloader](https://github.com/bezzad/Downloader) can be used to download files in parallel and with multiple chunks.
|
This [downloader](https://github.com/bezzad/Downloader) can be used to download files in parallel and with multiple chunks.
|
||||||
|
|
||||||
It has the following options:
|
It has the following options:
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ public enum DownloadClient
|
||||||
[Description("Internal Downloader")]
|
[Description("Internal Downloader")]
|
||||||
Internal,
|
Internal,
|
||||||
|
|
||||||
|
[Description("Bezzad Downloader")]
|
||||||
|
Bezzad,
|
||||||
|
|
||||||
[Description("Aria2c")]
|
[Description("Aria2c")]
|
||||||
Aria2c,
|
Aria2c,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
<PackageReference Include="AllDebrid.NET" Version="1.0.12" />
|
<PackageReference Include="AllDebrid.NET" Version="1.0.12" />
|
||||||
<PackageReference Include="Aria2.NET" Version="1.0.5" />
|
<PackageReference Include="Aria2.NET" Version="1.0.5" />
|
||||||
<PackageReference Include="Downloader" Version="3.0.6" />
|
<PackageReference Include="Downloader" Version="3.0.6" />
|
||||||
|
<PackageReference Include="Downloader.NET" Version="1.0.9" />
|
||||||
<PackageReference Include="MonoTorrent" Version="2.0.7" />
|
<PackageReference Include="MonoTorrent" Version="2.0.7" />
|
||||||
<PackageReference Include="Premiumize.NET" Version="1.0.4" />
|
<PackageReference Include="Premiumize.NET" Version="1.0.4" />
|
||||||
<PackageReference Include="RD.NET" Version="2.1.4" />
|
<PackageReference Include="RD.NET" Version="2.1.4" />
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ public class DownloadClient
|
||||||
Downloader = Settings.Get.DownloadClient.Client switch
|
Downloader = Settings.Get.DownloadClient.Client switch
|
||||||
{
|
{
|
||||||
Data.Enums.DownloadClient.Internal => new InternalDownloader(_download.Link, filePath),
|
Data.Enums.DownloadClient.Internal => new InternalDownloader(_download.Link, filePath),
|
||||||
|
Data.Enums.DownloadClient.Bezzad => new BezzadDownloader(_download.Link, filePath),
|
||||||
Data.Enums.DownloadClient.Aria2c => new Aria2cDownloader(_download.RemoteId, _download.Link, filePath, downloadPath),
|
Data.Enums.DownloadClient.Aria2c => new Aria2cDownloader(_download.RemoteId, _download.Link, filePath, downloadPath),
|
||||||
Data.Enums.DownloadClient.Symlink => new SymlinkDownloader(_download.Link, filePath),
|
Data.Enums.DownloadClient.Symlink => new SymlinkDownloader(_download.Link, filePath),
|
||||||
_ => throw new Exception($"Unknown download client {Settings.Get.DownloadClient}")
|
_ => throw new Exception($"Unknown download client {Settings.Get.DownloadClient}")
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,186 @@
|
||||||
|
using System.Net;
|
||||||
|
using Downloader;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
|
namespace RdtClient.Service.Services.Downloaders;
|
||||||
|
|
||||||
|
public class BezzadDownloader : IDownloader
|
||||||
|
{
|
||||||
|
public event EventHandler<DownloadCompleteEventArgs>? DownloadComplete;
|
||||||
|
public event EventHandler<DownloadProgressEventArgs>? DownloadProgress;
|
||||||
|
|
||||||
|
private readonly DownloadService _downloadService;
|
||||||
|
private readonly DownloadConfiguration _downloadConfiguration;
|
||||||
|
|
||||||
|
private readonly String _filePath;
|
||||||
|
private readonly String _uri;
|
||||||
|
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
private Boolean _finished;
|
||||||
|
|
||||||
|
public BezzadDownloader(String uri, String filePath)
|
||||||
|
{
|
||||||
|
_logger = Log.ForContext<BezzadDownloader>();
|
||||||
|
|
||||||
|
_uri = uri;
|
||||||
|
_filePath = filePath;
|
||||||
|
|
||||||
|
var settingProxyServer = Settings.Get.DownloadClient.ProxyServer;
|
||||||
|
|
||||||
|
// For all options, see https://github.com/bezzad/Downloader
|
||||||
|
_downloadConfiguration = new DownloadConfiguration
|
||||||
|
{
|
||||||
|
MaxTryAgainOnFailover = 5,
|
||||||
|
RangeDownload = false,
|
||||||
|
ClearPackageOnCompletionWithFailure = true,
|
||||||
|
ReserveStorageSpaceBeforeStartingDownload = false,
|
||||||
|
CheckDiskSizeBeforeDownload = false,
|
||||||
|
MaximumMemoryBufferBytes = 1024 * 1024 * 10,
|
||||||
|
RequestConfiguration =
|
||||||
|
{
|
||||||
|
Accept = "*/*",
|
||||||
|
UserAgent = $"rdt-client",
|
||||||
|
ProtocolVersion = HttpVersion.Version11,
|
||||||
|
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
|
||||||
|
KeepAlive = true,
|
||||||
|
UseDefaultCredentials = false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SetSettings();
|
||||||
|
|
||||||
|
if (!String.IsNullOrWhiteSpace(settingProxyServer))
|
||||||
|
{
|
||||||
|
_downloadConfiguration.RequestConfiguration.Proxy = new WebProxy(new Uri(settingProxyServer), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
_downloadService = new DownloadService(_downloadConfiguration);
|
||||||
|
|
||||||
|
_downloadService.DownloadProgressChanged += (_, args) =>
|
||||||
|
{
|
||||||
|
if (DownloadProgress == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DownloadProgress.Invoke(this,
|
||||||
|
new DownloadProgressEventArgs
|
||||||
|
{
|
||||||
|
Speed = (Int64)args.BytesPerSecondSpeed,
|
||||||
|
BytesDone = args.ReceivedBytesSize,
|
||||||
|
BytesTotal = args.TotalBytesToReceive
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
_downloadService.DownloadFileCompleted += (_, args) =>
|
||||||
|
{
|
||||||
|
String? error = null;
|
||||||
|
|
||||||
|
if (args.Cancelled)
|
||||||
|
{
|
||||||
|
error = $"The download was cancelled";
|
||||||
|
}
|
||||||
|
else if (args.Error != null)
|
||||||
|
{
|
||||||
|
error = args.Error.Message;
|
||||||
|
}
|
||||||
|
|
||||||
|
DownloadComplete?.Invoke(this,
|
||||||
|
new DownloadCompleteEventArgs
|
||||||
|
{
|
||||||
|
Error = error
|
||||||
|
});
|
||||||
|
|
||||||
|
_finished = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<String?> Download()
|
||||||
|
{
|
||||||
|
_logger.Debug($"Starting download of {_uri}, writing to path: {_filePath}");
|
||||||
|
|
||||||
|
_ = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await _downloadService.DownloadFileTaskAsync(_uri, _filePath);
|
||||||
|
});
|
||||||
|
|
||||||
|
_ = Task.Run(StartTimer);
|
||||||
|
|
||||||
|
return Task.FromResult<String?>(Guid.NewGuid().ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task Cancel()
|
||||||
|
{
|
||||||
|
_logger.Debug($"Cancelling download {_uri}");
|
||||||
|
|
||||||
|
_downloadService.CancelAsync();
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task Pause()
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task Resume()
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetSettings()
|
||||||
|
{
|
||||||
|
var settingDownloadMaxSpeed = Settings.Get.DownloadClient.MaxSpeed;
|
||||||
|
|
||||||
|
if (settingDownloadMaxSpeed <= 0)
|
||||||
|
{
|
||||||
|
settingDownloadMaxSpeed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
settingDownloadMaxSpeed = settingDownloadMaxSpeed * 1024 * 1024;
|
||||||
|
|
||||||
|
var settingDownloadTimeout = Settings.Get.DownloadClient.Timeout;
|
||||||
|
|
||||||
|
if (settingDownloadTimeout <= 0)
|
||||||
|
{
|
||||||
|
settingDownloadTimeout = 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
var settingParallelCount = Settings.Get.DownloadClient.ParallelCount;
|
||||||
|
|
||||||
|
if (settingParallelCount <= 0)
|
||||||
|
{
|
||||||
|
settingParallelCount = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Settings.Get.DownloadClient.ChunkCount <= 0)
|
||||||
|
{
|
||||||
|
_downloadConfiguration.ChunkCount = 8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_downloadConfiguration.ChunkCount = Settings.Get.DownloadClient.ChunkCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
_downloadConfiguration.MaximumBytesPerSecond = settingDownloadMaxSpeed;
|
||||||
|
_downloadConfiguration.ParallelDownload = settingParallelCount > 1;
|
||||||
|
_downloadConfiguration.ParallelCount = settingParallelCount;
|
||||||
|
_downloadConfiguration.Timeout = settingDownloadTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task StartTimer()
|
||||||
|
{
|
||||||
|
using var timer = new PeriodicTimer(TimeSpan.FromSeconds(5));
|
||||||
|
|
||||||
|
while (await timer.WaitForNextTickAsync())
|
||||||
|
{
|
||||||
|
if (_finished)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
using System.Net;
|
using Serilog;
|
||||||
using Downloader;
|
|
||||||
using Serilog;
|
|
||||||
|
|
||||||
namespace RdtClient.Service.Services.Downloaders;
|
namespace RdtClient.Service.Services.Downloaders;
|
||||||
|
|
||||||
|
|
@ -9,14 +7,16 @@ public class InternalDownloader : IDownloader
|
||||||
public event EventHandler<DownloadCompleteEventArgs>? DownloadComplete;
|
public event EventHandler<DownloadCompleteEventArgs>? DownloadComplete;
|
||||||
public event EventHandler<DownloadProgressEventArgs>? DownloadProgress;
|
public event EventHandler<DownloadProgressEventArgs>? DownloadProgress;
|
||||||
|
|
||||||
private readonly DownloadService _downloadService;
|
private readonly DownloaderNET.Downloader _downloadService;
|
||||||
private readonly DownloadConfiguration _downloadConfiguration;
|
private readonly DownloaderNET.Settings _downloadConfiguration;
|
||||||
|
|
||||||
private readonly String _filePath;
|
private readonly String _filePath;
|
||||||
private readonly String _uri;
|
private readonly String _uri;
|
||||||
|
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
|
private readonly CancellationTokenSource _cancellationToken = new();
|
||||||
|
|
||||||
private Boolean _finished;
|
private Boolean _finished;
|
||||||
|
|
||||||
public InternalDownloader(String uri, String filePath)
|
public InternalDownloader(String uri, String filePath)
|
||||||
|
|
@ -26,38 +26,15 @@ public class InternalDownloader : IDownloader
|
||||||
_uri = uri;
|
_uri = uri;
|
||||||
_filePath = filePath;
|
_filePath = filePath;
|
||||||
|
|
||||||
var settingProxyServer = Settings.Get.DownloadClient.ProxyServer;
|
_downloadConfiguration = new DownloaderNET.Settings();
|
||||||
|
|
||||||
// For all options, see https://github.com/bezzad/Downloader
|
|
||||||
_downloadConfiguration = new DownloadConfiguration
|
|
||||||
{
|
|
||||||
MaxTryAgainOnFailover = 5,
|
|
||||||
RangeDownload = false,
|
|
||||||
ClearPackageOnCompletionWithFailure = true,
|
|
||||||
ReserveStorageSpaceBeforeStartingDownload = false,
|
|
||||||
CheckDiskSizeBeforeDownload = false,
|
|
||||||
MaximumMemoryBufferBytes = 1024 * 1024 * 10,
|
|
||||||
RequestConfiguration =
|
|
||||||
{
|
|
||||||
Accept = "*/*",
|
|
||||||
UserAgent = $"rdt-client",
|
|
||||||
ProtocolVersion = HttpVersion.Version11,
|
|
||||||
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
|
|
||||||
KeepAlive = true,
|
|
||||||
UseDefaultCredentials = false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
SetSettings();
|
SetSettings();
|
||||||
|
|
||||||
if (!String.IsNullOrWhiteSpace(settingProxyServer))
|
_downloadService = new DownloaderNET.Downloader(_uri, _filePath, _downloadConfiguration);
|
||||||
{
|
|
||||||
_downloadConfiguration.RequestConfiguration.Proxy = new WebProxy(new Uri(settingProxyServer), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
_downloadService = new DownloadService(_downloadConfiguration);
|
//_downloadService.OnLog += message => Debug.WriteLine(message.Message);
|
||||||
|
|
||||||
_downloadService.DownloadProgressChanged += (_, args) =>
|
_downloadService.OnProgress += (chunks, _) =>
|
||||||
{
|
{
|
||||||
if (DownloadProgress == null)
|
if (DownloadProgress == null)
|
||||||
{
|
{
|
||||||
|
|
@ -67,54 +44,41 @@ public class InternalDownloader : IDownloader
|
||||||
DownloadProgress.Invoke(this,
|
DownloadProgress.Invoke(this,
|
||||||
new DownloadProgressEventArgs
|
new DownloadProgressEventArgs
|
||||||
{
|
{
|
||||||
Speed = (Int64)args.BytesPerSecondSpeed,
|
Speed = (Int64)chunks.Where(m => m.IsActive).Sum(m => m.Speed),
|
||||||
BytesDone = args.ReceivedBytesSize,
|
BytesDone = chunks.Sum(m => m.DownloadBytes),
|
||||||
BytesTotal = args.TotalBytesToReceive
|
BytesTotal = chunks.Sum(m => m.LengthBytes)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
_downloadService.DownloadFileCompleted += (_, args) =>
|
_downloadService.OnComplete += (_, error) =>
|
||||||
{
|
{
|
||||||
String? error = null;
|
|
||||||
|
|
||||||
if (args.Cancelled)
|
|
||||||
{
|
|
||||||
error = $"The download was cancelled";
|
|
||||||
}
|
|
||||||
else if (args.Error != null)
|
|
||||||
{
|
|
||||||
error = args.Error.Message;
|
|
||||||
}
|
|
||||||
|
|
||||||
DownloadComplete?.Invoke(this,
|
DownloadComplete?.Invoke(this,
|
||||||
new DownloadCompleteEventArgs
|
new DownloadCompleteEventArgs
|
||||||
{
|
{
|
||||||
Error = error
|
Error = error?.Message
|
||||||
});
|
});
|
||||||
|
|
||||||
_finished = true;
|
_finished = true;
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<String?> Download()
|
public async Task<String?> Download()
|
||||||
{
|
{
|
||||||
_logger.Debug($"Starting download of {_uri}, writing to path: {_filePath}");
|
_logger.Debug($"Starting download of {_uri}, writing to path: {_filePath}");
|
||||||
|
|
||||||
_ = Task.Run(async () =>
|
await _downloadService.Download(_cancellationToken.Token);
|
||||||
{
|
|
||||||
await _downloadService.DownloadFileTaskAsync(_uri, _filePath);
|
|
||||||
});
|
|
||||||
|
|
||||||
_ = Task.Run(StartTimer);
|
_ = Task.Run(StartTimer);
|
||||||
|
|
||||||
return Task.FromResult<String?>(Guid.NewGuid().ToString());
|
return Guid.NewGuid().ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Cancel()
|
public Task Cancel()
|
||||||
{
|
{
|
||||||
_logger.Debug($"Cancelling download {_uri}");
|
_logger.Debug($"Cancelling download {_uri}");
|
||||||
|
|
||||||
_downloadService.CancelAsync();
|
_cancellationToken.Cancel(false);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
@ -131,6 +95,13 @@ public class InternalDownloader : IDownloader
|
||||||
|
|
||||||
private void SetSettings()
|
private void SetSettings()
|
||||||
{
|
{
|
||||||
|
var settingDownloadParallelCount = Settings.Get.DownloadClient.ParallelCount;
|
||||||
|
|
||||||
|
if (settingDownloadParallelCount <= 0)
|
||||||
|
{
|
||||||
|
settingDownloadParallelCount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
var settingDownloadMaxSpeed = Settings.Get.DownloadClient.MaxSpeed;
|
var settingDownloadMaxSpeed = Settings.Get.DownloadClient.MaxSpeed;
|
||||||
|
|
||||||
if (settingDownloadMaxSpeed <= 0)
|
if (settingDownloadMaxSpeed <= 0)
|
||||||
|
|
@ -147,26 +118,10 @@ public class InternalDownloader : IDownloader
|
||||||
settingDownloadTimeout = 1000;
|
settingDownloadTimeout = 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
var settingParallelCount = Settings.Get.DownloadClient.ParallelCount;
|
_downloadConfiguration.Parallel = settingDownloadParallelCount;
|
||||||
|
|
||||||
if (settingParallelCount <= 0)
|
|
||||||
{
|
|
||||||
settingParallelCount = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Settings.Get.DownloadClient.ChunkCount <= 0)
|
|
||||||
{
|
|
||||||
_downloadConfiguration.ChunkCount = 8;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_downloadConfiguration.ChunkCount = Settings.Get.DownloadClient.ChunkCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
_downloadConfiguration.MaximumBytesPerSecond = settingDownloadMaxSpeed;
|
_downloadConfiguration.MaximumBytesPerSecond = settingDownloadMaxSpeed;
|
||||||
_downloadConfiguration.ParallelDownload = settingParallelCount > 1;
|
|
||||||
_downloadConfiguration.ParallelCount = settingParallelCount;
|
|
||||||
_downloadConfiguration.Timeout = settingDownloadTimeout;
|
_downloadConfiguration.Timeout = settingDownloadTimeout;
|
||||||
|
_downloadConfiguration.RetryCount = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task StartTimer()
|
private async Task StartTimer()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue