From 580ceb8c3c8d1bfff596a6b0a1d87e6f8e29ccc9 Mon Sep 17 00:00:00 2001 From: qwsdcvghyu89 <61093706+qwsdcvghyu89@users.noreply.github.com> Date: Sun, 16 Nov 2025 01:11:22 +1100 Subject: [PATCH] Add FollowRedirects option to downloader Introduces a FollowRedirects property to UnitDownloaderOptions and its builder, allowing control over HTTP redirect behavior. Updates UnitDownloader to use this option, following redirects when enabled and reporting progress accordingly. --- Beam.Downloaders/UnitDownloader.cs | 13 +++++++++++-- Beam.Downloaders/UnitDownloaderOptions.cs | 2 ++ Beam.Downloaders/UnitDownloaderOptionsBuilder.cs | 7 +++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Beam.Downloaders/UnitDownloader.cs b/Beam.Downloaders/UnitDownloader.cs index cad1ccc..45078ea 100644 --- a/Beam.Downloaders/UnitDownloader.cs +++ b/Beam.Downloaders/UnitDownloader.cs @@ -25,8 +25,17 @@ namespace Beam.Downloaders { protected virtual async Task DownloadToStream(string url, int bufferSize, Stream destinationStream, IProgress progress, CancellationToken ct) { - - var stream = await Client.GetStreamAsync(url, ct); + if (options.FollowRedirects) { + var response = await Client.GetAsync(url, ct); // automatically follows redirects + await response.Content.CopyToAsync(destinationStream, ct); + progress?.Report(new DownloadReport() { + BytesDownloaded = destinationStream.Length, + BytesRemaining = 0 + }); + return; + } + + var stream = await Client.GetStreamAsync(url, ct); // does not follow redirects byte[] buffer = new byte[bufferSize]; int inBuffer = 0; long downloaded = 0; diff --git a/Beam.Downloaders/UnitDownloaderOptions.cs b/Beam.Downloaders/UnitDownloaderOptions.cs index 421c3b6..26a6ae5 100644 --- a/Beam.Downloaders/UnitDownloaderOptions.cs +++ b/Beam.Downloaders/UnitDownloaderOptions.cs @@ -24,6 +24,8 @@ public record class UnitDownloaderOptions { public string? DownloadFolder { get; init; } = null; public int BufferSize { get; init; } = 80 * 1024; // 80kb + public bool FollowRedirects { get; init; } = true; + public string GetFileNameForDownload(string url, byte[] additionalData) { byte[] bytes = [..Encoding.UTF8.GetBytes(url), ..additionalData]; var name = Convert.ToBase64String(System.IO.Hashing.XxHash64.Hash(bytes)); diff --git a/Beam.Downloaders/UnitDownloaderOptionsBuilder.cs b/Beam.Downloaders/UnitDownloaderOptionsBuilder.cs index 4675092..fb1ad40 100644 --- a/Beam.Downloaders/UnitDownloaderOptionsBuilder.cs +++ b/Beam.Downloaders/UnitDownloaderOptionsBuilder.cs @@ -13,11 +13,17 @@ public sealed class UnitDownloaderOptionsBuilder { private AsyncTransformer? _asyncTransformer; private string? _downloadFolder = null; private int _bufferSize = 80 * 1024; + private bool _followRedirects = true; public UnitDownloaderOptionsBuilder WithTarget(DownloadTarget target) { _target = target; return this; } + + public UnitDownloaderOptionsBuilder WithFollowRedirects(bool followRedirects) { + _followRedirects = followRedirects; + return this; + } public UnitDownloaderOptionsBuilder WithClient(HttpClient client) { @@ -98,6 +104,7 @@ public sealed class UnitDownloaderOptionsBuilder { Client = _client, FailurePredicateOptions = _failurePredicateOptionsOverride, SkipPredicateOptions = _skipPredicateOptionsOverride, + FollowRedirects = _followRedirects, FragmentOptions = _fragmentOptions, AsyncTransformer = _asyncTransformer, DownloadFolder = _downloadFolder,