Browse Source

Add cancellation token for download service

pull/109/head
Ionite 1 year ago
parent
commit
0e0ccd0fb7
No known key found for this signature in database
  1. 78
      StabilityMatrix.Core/Services/DownloadService.cs
  2. 9
      StabilityMatrix.Core/Services/IDownloadService.cs

78
StabilityMatrix.Core/Services/DownloadService.cs

@ -17,43 +17,66 @@ public class DownloadService : IDownloadService
this.httpClientFactory = httpClientFactory;
}
public async Task DownloadToFileAsync(string downloadUrl, string downloadPath,
IProgress<ProgressReport>? progress = null, string? httpClientName = null)
public async Task DownloadToFileAsync(
string downloadUrl,
string downloadPath,
IProgress<ProgressReport>? progress = null,
string? httpClientName = null,
CancellationToken cancellationToken = default
)
{
using var client = string.IsNullOrWhiteSpace(httpClientName)
? httpClientFactory.CreateClient()
: httpClientFactory.CreateClient(httpClientName);
client.Timeout = TimeSpan.FromMinutes(10);
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("StabilityMatrix", "2.0"));
await using var file = new FileStream(downloadPath, FileMode.Create, FileAccess.Write, FileShare.None);
client.DefaultRequestHeaders.UserAgent.Add(
new ProductInfoHeaderValue("StabilityMatrix", "2.0")
);
await using var file = new FileStream(
downloadPath,
FileMode.Create,
FileAccess.Write,
FileShare.None
);
long contentLength = 0;
var response = await client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead);
var response = await client
.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead, cancellationToken)
.ConfigureAwait(false);
contentLength = response.Content.Headers.ContentLength ?? 0;
var delays = Backoff.DecorrelatedJitterBackoffV2(
TimeSpan.FromMilliseconds(50), retryCount: 3);
TimeSpan.FromMilliseconds(50),
retryCount: 3
);
foreach (var delay in delays)
{
if (contentLength > 0) break;
if (contentLength > 0)
break;
logger.LogDebug("Retrying get-headers for content-length");
await Task.Delay(delay);
response = await client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead);
await Task.Delay(delay, cancellationToken).ConfigureAwait(false);
response = await client
.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead, cancellationToken)
.ConfigureAwait(false);
contentLength = response.Content.Headers.ContentLength ?? 0;
}
var isIndeterminate = contentLength == 0;
await using var stream = await response.Content.ReadAsStreamAsync();
await using var stream = await response.Content
.ReadAsStreamAsync(cancellationToken)
.ConfigureAwait(false);
var totalBytesRead = 0L;
var buffer = new byte[BufferSize];
while (true)
{
var bytesRead = await stream.ReadAsync(buffer);
if (bytesRead == 0) break;
await file.WriteAsync(buffer.AsMemory(0, bytesRead));
var bytesRead = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
if (bytesRead == 0)
break;
await file.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken)
.ConfigureAwait(false);
totalBytesRead += bytesRead;
@ -63,13 +86,18 @@ public class DownloadService : IDownloadService
}
else
{
progress?.Report(new ProgressReport(current: Convert.ToUInt64(totalBytesRead),
total: Convert.ToUInt64(contentLength), message: "Downloading..."));
progress?.Report(
new ProgressReport(
current: Convert.ToUInt64(totalBytesRead),
total: Convert.ToUInt64(contentLength),
message: "Downloading..."
)
);
}
}
await file.FlushAsync();
await file.FlushAsync(cancellationToken).ConfigureAwait(false);
progress?.Report(new ProgressReport(1f, message: "Download complete!"));
}
@ -77,11 +105,13 @@ public class DownloadService : IDownloadService
{
using var client = httpClientFactory.CreateClient();
client.Timeout = TimeSpan.FromSeconds(10);
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("StabilityMatrix", "2.0"));
client.DefaultRequestHeaders.UserAgent.Add(
new ProductInfoHeaderValue("StabilityMatrix", "2.0")
);
try
{
var response = await client.GetAsync(url);
return await response.Content.ReadAsStreamAsync();
var response = await client.GetAsync(url).ConfigureAwait(false);
return await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
}
catch (Exception e)
{

9
StabilityMatrix.Core/Services/IDownloadService.cs

@ -4,8 +4,13 @@ namespace StabilityMatrix.Core.Services;
public interface IDownloadService
{
Task DownloadToFileAsync(string downloadUrl, string downloadPath,
IProgress<ProgressReport>? progress = null, string? httpClientName = null);
Task DownloadToFileAsync(
string downloadUrl,
string downloadPath,
IProgress<ProgressReport>? progress = null,
string? httpClientName = null,
CancellationToken cancellationToken = default
);
Task<Stream> GetImageStreamFromUrl(string url);
}

Loading…
Cancel
Save