Switch the internal downloader (again).
This commit is contained in:
parent
6ad51b036e
commit
8114baa7b8
3 changed files with 98 additions and 27 deletions
|
|
@ -99,6 +99,10 @@ public class DbSettingsDownloadClient
|
||||||
[Description("Maximum amount of parallel threads that are used to download a single file to your host. If set to 0 no parallel downloading will be done.")]
|
[Description("Maximum amount of parallel threads that are used to download a single file to your host. If set to 0 no parallel downloading will be done.")]
|
||||||
public Int32 ParallelCount { get; set; } = 0;
|
public Int32 ParallelCount { get; set; } = 0;
|
||||||
|
|
||||||
|
[DisplayName("Chunk Count")]
|
||||||
|
[Description("Split the downloaded file in this amount of chunks. If left to 0, automatically deteremine the chunk size based on the file size.")]
|
||||||
|
public Int32 ChunkCount { get; set; } = 0;
|
||||||
|
|
||||||
[DisplayName("Connection Timeout (only used for the Internal Downloader)")]
|
[DisplayName("Connection Timeout (only used for the Internal Downloader)")]
|
||||||
[Description("Timeout in milliseconds before the downloader times out.")]
|
[Description("Timeout in milliseconds before the downloader times out.")]
|
||||||
public Int32 Timeout { get; set; } = 5000;
|
public Int32 Timeout { get; set; } = 5000;
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,13 @@
|
||||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||||
<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.NET" Version="1.0.9" />
|
<PackageReference Include="Downloader" Version="3.0.6" />
|
||||||
<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" />
|
||||||
<PackageReference Include="Serilog" Version="3.1.1" />
|
<PackageReference Include="Serilog" Version="3.1.1" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.34.2" />
|
<PackageReference Include="SharpCompress" Version="0.35.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using DownloaderNET;
|
using System.Net;
|
||||||
|
using Downloader;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
namespace RdtClient.Service.Services.Downloaders;
|
namespace RdtClient.Service.Services.Downloaders;
|
||||||
|
|
@ -8,16 +9,14 @@ 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 Downloader _downloadService;
|
private readonly DownloadService _downloadService;
|
||||||
private readonly DownloaderNET.Settings _downloadConfiguration;
|
private readonly DownloadConfiguration _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)
|
||||||
|
|
@ -27,15 +26,39 @@ public class InternalDownloader : IDownloader
|
||||||
_uri = uri;
|
_uri = uri;
|
||||||
_filePath = filePath;
|
_filePath = filePath;
|
||||||
|
|
||||||
_downloadConfiguration = new DownloaderNET.Settings();
|
var settingProxyServer = Settings.Get.DownloadClient.ProxyServer;
|
||||||
|
|
||||||
|
// For all options, see https://github.com/bezzad/Downloader
|
||||||
|
_downloadConfiguration = new DownloadConfiguration
|
||||||
|
{
|
||||||
|
BufferBlockSize = 1024 * 8,
|
||||||
|
MaxTryAgainOnFailover = 5,
|
||||||
|
RangeDownload = false,
|
||||||
|
ClearPackageOnCompletionWithFailure = false,
|
||||||
|
MinimumSizeOfChunking = 1024,
|
||||||
|
ReserveStorageSpaceBeforeStartingDownload = false,
|
||||||
|
CheckDiskSizeBeforeDownload = true,
|
||||||
|
RequestConfiguration =
|
||||||
|
{
|
||||||
|
Accept = "*/*",
|
||||||
|
UserAgent = $"rdt-client",
|
||||||
|
ProtocolVersion = HttpVersion.Version11,
|
||||||
|
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
|
||||||
|
KeepAlive = true,
|
||||||
|
UseDefaultCredentials = false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
SetSettings();
|
SetSettings();
|
||||||
|
|
||||||
_downloadService = new Downloader(_uri, _filePath, _downloadConfiguration);
|
if (!String.IsNullOrWhiteSpace(settingProxyServer))
|
||||||
|
{
|
||||||
|
_downloadConfiguration.RequestConfiguration.Proxy = new WebProxy(new Uri(settingProxyServer), false);
|
||||||
|
}
|
||||||
|
|
||||||
//_downloadService.OnLog += message => Debug.WriteLine(message.Message);
|
_downloadService = new DownloadService(_downloadConfiguration);
|
||||||
|
|
||||||
_downloadService.OnProgress += (chunks, _) =>
|
_downloadService.DownloadProgressChanged += (_, args) =>
|
||||||
{
|
{
|
||||||
if (DownloadProgress == null)
|
if (DownloadProgress == null)
|
||||||
{
|
{
|
||||||
|
|
@ -45,41 +68,68 @@ public class InternalDownloader : IDownloader
|
||||||
DownloadProgress.Invoke(this,
|
DownloadProgress.Invoke(this,
|
||||||
new DownloadProgressEventArgs
|
new DownloadProgressEventArgs
|
||||||
{
|
{
|
||||||
Speed = (Int64)chunks.Where(m => m.IsActive).Sum(m => m.Speed),
|
Speed = (Int64)args.BytesPerSecondSpeed,
|
||||||
BytesDone = chunks.Sum(m => m.DownloadBytes),
|
BytesDone = args.ReceivedBytesSize,
|
||||||
BytesTotal = chunks.Sum(m => m.LengthBytes)
|
BytesTotal = args.TotalBytesToReceive
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
_downloadService.OnComplete += (_, error) =>
|
_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,
|
DownloadComplete?.Invoke(this,
|
||||||
new DownloadCompleteEventArgs
|
new DownloadCompleteEventArgs
|
||||||
{
|
{
|
||||||
Error = error?.Message
|
Error = error
|
||||||
});
|
});
|
||||||
|
|
||||||
_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));
|
if (Settings.Get.DownloadClient.ChunkCount == 0)
|
||||||
Task.Run(StartTimer);
|
{
|
||||||
|
var contentSize = await GetContentSize();
|
||||||
|
|
||||||
return Task.FromResult<String?>(null);
|
var chunkSize = contentSize switch
|
||||||
|
{
|
||||||
|
<= 1024 * 1024 * 10 => 1024 * 1024 * 10,
|
||||||
|
<= 1024 * 1024 * 100 => 1024 * 1024 * 25,
|
||||||
|
_ => 1024 * 1024 * 50
|
||||||
|
};
|
||||||
|
|
||||||
|
_downloadConfiguration.ChunkCount = (Int32) Math.Ceiling(contentSize / (Double) chunkSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await _downloadService.DownloadFileTaskAsync(_uri, _filePath);
|
||||||
|
});
|
||||||
|
|
||||||
|
_ = Task.Run(StartTimer);
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Cancel()
|
public Task Cancel()
|
||||||
{
|
{
|
||||||
_logger.Debug($"Cancelling download {_uri}");
|
_logger.Debug($"Cancelling download {_uri}");
|
||||||
|
|
||||||
_cancellationToken.Cancel(false);
|
_downloadService.CancelAsync();
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
@ -119,10 +169,10 @@ public class InternalDownloader : IDownloader
|
||||||
settingDownloadTimeout = 1000;
|
settingDownloadTimeout = 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
_downloadConfiguration.Parallel = settingDownloadParallelCount;
|
|
||||||
_downloadConfiguration.MaximumBytesPerSecond = settingDownloadMaxSpeed;
|
_downloadConfiguration.MaximumBytesPerSecond = settingDownloadMaxSpeed;
|
||||||
|
_downloadConfiguration.ParallelDownload = settingDownloadParallelCount > 1;
|
||||||
|
_downloadConfiguration.ParallelCount = settingDownloadParallelCount;
|
||||||
_downloadConfiguration.Timeout = settingDownloadTimeout;
|
_downloadConfiguration.Timeout = settingDownloadTimeout;
|
||||||
_downloadConfiguration.RetryCount = 5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task StartTimer()
|
private async Task StartTimer()
|
||||||
|
|
@ -139,4 +189,21 @@ public class InternalDownloader : IDownloader
|
||||||
SetSettings();
|
SetSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<Int64> GetContentSize()
|
||||||
|
{
|
||||||
|
var httpClient = new HttpClient();
|
||||||
|
var responseHeaders = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, _uri));
|
||||||
|
|
||||||
|
if (!responseHeaders.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
var content = await responseHeaders.Content.ReadAsStringAsync();
|
||||||
|
var ex = new Exception($"Unable to retrieve content size before downloading, received response: {responseHeaders.StatusCode} {content}");
|
||||||
|
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = responseHeaders.Content.Headers.ContentLength ?? -1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue