SPT-AKI-Installer/SPTInstaller/Helpers/HttpClientProgressExtensions.cs
2024-05-01 10:31:55 -04:00

59 lines
2.6 KiB
C#

using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace SPTInstaller.Helpers;
public static class HttpClientProgressExtensions
{
public static async Task DownloadDataAsync(this HttpClient client, string requestUrl, Stream destination,
IProgress<double> progress = null, CancellationToken cancellationToken = default(CancellationToken))
{
using (var response = await client.GetAsync(requestUrl, HttpCompletionOption.ResponseHeadersRead))
{
var contentLength = response.Content.Headers.ContentLength;
using (var download = await response.Content.ReadAsStreamAsync())
{
// no progress... no contentLength... very sad
if (progress is null || !contentLength.HasValue)
{
await download.CopyToAsync(destination);
return;
}
// Such progress and contentLength much reporting Wow!
var progressWrapper = new Progress<long>(totalBytes =>
progress.Report(GetProgressPercentage(totalBytes, contentLength.Value)));
await download.CopyToAsync(destination, 81920, progressWrapper, cancellationToken);
}
}
float GetProgressPercentage(float totalBytes, float currentBytes) => (totalBytes / currentBytes) * 100f;
}
static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize,
IProgress<long> progress = null, CancellationToken cancellationToken = default(CancellationToken))
{
if (bufferSize < 0)
throw new ArgumentOutOfRangeException(nameof(bufferSize));
if (source is null)
throw new ArgumentNullException(nameof(source));
if (!source.CanRead)
throw new InvalidOperationException($"'{nameof(source)}' is not readable.");
if (destination == null)
throw new ArgumentNullException(nameof(destination));
if (!destination.CanWrite)
throw new InvalidOperationException($"'{nameof(destination)}' is not writable.");
var buffer = new byte[bufferSize];
long totalBytesRead = 0;
int bytesRead;
while ((bytesRead =
await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
{
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
totalBytesRead += bytesRead;
progress?.Report(totalBytesRead);
}
}
}