Skip to content

Commit

Permalink
make downloader more robust
Browse files Browse the repository at this point in the history
  • Loading branch information
the-database committed Aug 16, 2024
1 parent 84cd12a commit 0f37734
Showing 1 changed file with 58 additions and 16 deletions.
74 changes: 58 additions & 16 deletions VideoJaNai/Services/Downloader.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

Expand All @@ -10,29 +11,70 @@ public class Downloader
{
public delegate void ProgressChanged(double percentage);

public static async Task DownloadFileAsync(string url, string destinationFilePath, ProgressChanged progressChanged)
public static async Task DownloadFileAsync(string url, string destinationFilePath, ProgressChanged progressChanged, int maxRetries = 10)
{
using HttpClient client = new();
using HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
long totalBytes = 0;
long totalRead = 0;
int retryCount = 0;
bool downloadComplete = false;

response.EnsureSuccessStatusCode();
while (!downloadComplete && retryCount < maxRetries)
{
try
{
using HttpClient client = new();
using HttpRequestMessage request = new(HttpMethod.Get, url)
{
Version = HttpVersion.Version30
};

long totalBytes = response.Content.Headers.ContentLength ?? -1L;
using Stream contentStream = await response.Content.ReadAsStreamAsync(), fileStream = new FileStream(destinationFilePath, FileMode.Create, FileAccess.Write, FileShare.None, 8192, true);
if (totalRead > 0)
{
request.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(totalRead, null); // resume
}

var totalRead = 0L;
var buffer = new byte[8192];
int read;
using HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
response.EnsureSuccessStatusCode();

while ((read = await contentStream.ReadAsync(buffer)) > 0)
{
await fileStream.WriteAsync(buffer.AsMemory(0, read));
totalRead += read;
totalBytes = response.Content.Headers.ContentLength ?? -1L;
using Stream contentStream = await response.Content.ReadAsStreamAsync(),
fileStream = new FileStream(destinationFilePath, FileMode.Append, FileAccess.Write, FileShare.None, 8192, true);

var buffer = new byte[8192];
int read;

while ((read = await contentStream.ReadAsync(buffer)) > 0)
{
await fileStream.WriteAsync(buffer.AsMemory(0, read));
totalRead += read;

if (totalBytes != -1)
if (totalBytes != -1)
{
double percentage = Math.Round((double)totalRead / totalBytes * 100, 0);
progressChanged?.Invoke(percentage);
}
}

downloadComplete = true;
}
catch (HttpRequestException e)
{
retryCount++;
if (retryCount >= maxRetries)
{
throw; // Re-throw if max retries are reached
}

await Task.Delay(TimeSpan.FromSeconds(2 * retryCount));
}
catch (TaskCanceledException e)
{
double percentage = Math.Round((double)totalRead / totalBytes * 100, 0);
progressChanged?.Invoke(percentage);
retryCount++;
if (retryCount >= maxRetries)
{
throw new Exception("The download was canceled or timed out.", e);
}
await Task.Delay(TimeSpan.FromSeconds(2 * retryCount));
}
}
}
Expand Down

0 comments on commit 0f37734

Please sign in to comment.