From 3ff44339b5150363a1b42ce1c2af185cab1297fe Mon Sep 17 00:00:00 2001 From: glax Date: Fri, 10 Oct 2025 18:23:27 +0200 Subject: [PATCH] Fix #468 failed downloads (Task cancelled) results in empty chapter archive --- API/MangaConnectors/MangaConnector.cs | 6 +++++ API/MangaDownloadClients/DownloadClient.cs | 3 ++- .../FlareSolverrDownloadClient.cs | 6 ++--- .../HttpDownloadClient.cs | 4 ++-- ...DownloadChapterFromMangaconnectorWorker.cs | 24 ++++++------------- 5 files changed, 20 insertions(+), 23 deletions(-) diff --git a/API/MangaConnectors/MangaConnector.cs b/API/MangaConnectors/MangaConnector.cs index 5514c0f..71e3420 100644 --- a/API/MangaConnectors/MangaConnector.cs +++ b/API/MangaConnectors/MangaConnector.cs @@ -84,4 +84,10 @@ public abstract class MangaConnector(string name, string[] supportedLanguages, s return filename.CleanNameForWindows(); } + + public async Task DownloadImage(string imageUrl, CancellationToken ct) + { + HttpResponseMessage requestResult = await downloadClient.MakeRequest(imageUrl, RequestType.MangaImage, cancellationToken: ct); + return requestResult.IsSuccessStatusCode ? await requestResult.Content.ReadAsStreamAsync(ct) : null; + } } \ No newline at end of file diff --git a/API/MangaDownloadClients/DownloadClient.cs b/API/MangaDownloadClients/DownloadClient.cs index 6cce650..e1fb0d4 100644 --- a/API/MangaDownloadClients/DownloadClient.cs +++ b/API/MangaDownloadClients/DownloadClient.cs @@ -2,5 +2,6 @@ public interface IDownloadClient { - internal Task MakeRequest(string url, RequestType requestType, string? referrer = null); + internal Task MakeRequest(string url, RequestType requestType, string? referrer = null, + CancellationToken? cancellationToken = null); } \ No newline at end of file diff --git a/API/MangaDownloadClients/FlareSolverrDownloadClient.cs b/API/MangaDownloadClients/FlareSolverrDownloadClient.cs index 86dd1c5..982145b 100644 --- a/API/MangaDownloadClients/FlareSolverrDownloadClient.cs +++ b/API/MangaDownloadClients/FlareSolverrDownloadClient.cs @@ -12,7 +12,7 @@ public class FlareSolverrDownloadClient(HttpClient client) : IDownloadClient { private ILog Log { get; } = LogManager.GetLogger(typeof(FlareSolverrDownloadClient)); - public async Task MakeRequest(string url, RequestType requestType, string? referrer = null) + public async Task MakeRequest(string url, RequestType requestType, string? referrer = null, CancellationToken? cancellationToken = null) { Log.Debug($"Using {typeof(FlareSolverrDownloadClient).FullName} for {url}"); if(referrer is not null) @@ -46,7 +46,7 @@ public class FlareSolverrDownloadClient(HttpClient client) : IDownloadClient HttpResponseMessage? response; try { - response = await client.SendAsync(requestMessage); + response = await client.SendAsync(requestMessage, cancellationToken ?? CancellationToken.None); } catch (HttpRequestException e) { @@ -71,7 +71,7 @@ public class FlareSolverrDownloadClient(HttpClient client) : IDownloadClient return response; } - string responseString = response.Content.ReadAsStringAsync().Result; + string responseString = await response.Content.ReadAsStringAsync(cancellationToken ?? CancellationToken.None); JObject responseObj = JObject.Parse(responseString); if (!IsInCorrectFormat(responseObj, out string? reason)) { diff --git a/API/MangaDownloadClients/HttpDownloadClient.cs b/API/MangaDownloadClients/HttpDownloadClient.cs index e4b5eea..e15c8c4 100644 --- a/API/MangaDownloadClients/HttpDownloadClient.cs +++ b/API/MangaDownloadClients/HttpDownloadClient.cs @@ -14,7 +14,7 @@ internal class HttpDownloadClient : IDownloadClient private static readonly FlareSolverrDownloadClient FlareSolverrDownloadClient = new(Client); private ILog Log { get; } = LogManager.GetLogger(typeof(HttpDownloadClient)); - public async Task MakeRequest(string url, RequestType requestType, string? referrer = null) + public async Task MakeRequest(string url, RequestType requestType, string? referrer = null, CancellationToken? cancellationToken = null) { Log.Debug($"Using {typeof(HttpDownloadClient).FullName} for {url}"); HttpRequestMessage requestMessage = new(HttpMethod.Get, url); @@ -24,7 +24,7 @@ internal class HttpDownloadClient : IDownloadClient try { - HttpResponseMessage response = await Client.SendAsync(requestMessage); + HttpResponseMessage response = await Client.SendAsync(requestMessage, cancellationToken ?? CancellationToken.None); Log.Debug($"Request {url} returned {(int)response.StatusCode} {response.StatusCode}"); if(response.IsSuccessStatusCode) return response; diff --git a/API/Workers/MangaDownloadWorkers/DownloadChapterFromMangaconnectorWorker.cs b/API/Workers/MangaDownloadWorkers/DownloadChapterFromMangaconnectorWorker.cs index 06ca3ff..8d8c799 100644 --- a/API/Workers/MangaDownloadWorkers/DownloadChapterFromMangaconnectorWorker.cs +++ b/API/Workers/MangaDownloadWorkers/DownloadChapterFromMangaconnectorWorker.cs @@ -102,18 +102,19 @@ public class DownloadChapterFromMangaconnectorWorker(MangaConnectorId c { try { - if (DownloadImage(imageUrl) is not { } stream) + if (await mangaConnector.DownloadImage(imageUrl, CancellationToken) is not { } stream) { Log.Error($"Failed to download image: {imageUrl}"); return []; } else - images.Add(stream); + images.Add(await ProcessImage(stream, CancellationToken)); } catch (Exception ex) { Log.Error(ex); images.ForEach(i => i.Dispose()); + return []; } } @@ -186,7 +187,7 @@ public class DownloadChapterFromMangaconnectorWorker(MangaConnectorId c }; private async Task AllDownloadsFinished() => (await StartNewChapterDownloadsWorker.GetMissingChapters(DbContext, CancellationToken)).Count == 0; - private Stream ProcessImage(Stream imageStream) + private async Task ProcessImage(Stream imageStream, CancellationToken? cancellationToken = null) { Log.Debug("Processing image"); imageStream.Position = 0; @@ -199,11 +200,11 @@ public class DownloadChapterFromMangaconnectorWorker(MangaConnectorId c MemoryStream processedImage = new (); try { - using Image image = Image.Load(imageStream); + using Image image = await Image.LoadAsync(imageStream, cancellationToken ?? CancellationToken.None); Log.Debug("Image loaded"); if (Tranga.Settings.BlackWhiteImages) image.Mutate(i => i.ApplyProcessor(new AdaptiveThresholdProcessor())); - image.SaveAsJpeg(processedImage, new JpegEncoder() + await image.SaveAsJpegAsync(processedImage, new JpegEncoder() { Quality = Tranga.Settings.ImageCompression }); @@ -225,7 +226,7 @@ public class DownloadChapterFromMangaconnectorWorker(MangaConnectorId c { Log.Error(e); } - imageStream.CopyTo(processedImage); + await imageStream.CopyToAsync(processedImage); processedImage.Position = 0; return processedImage; } @@ -286,16 +287,5 @@ public class DownloadChapterFromMangaconnectorWorker(MangaConnectorId c Log.Debug($"Copied cover from {fullCoverPath} to {newFilePath}"); } - private Stream? DownloadImage(string imageUrl) - { - HttpDownloadClient downloadClient = new(); - HttpResponseMessage requestResult = downloadClient.MakeRequest(imageUrl, RequestType.MangaImage).Result; - - if ((int)requestResult.StatusCode < 200 || (int)requestResult.StatusCode >= 300) - return null; - - return ProcessImage(requestResult.Content.ReadAsStream()); - } - public override string ToString() => $"{base.ToString()} {_mangaConnectorIdId}"; } \ No newline at end of file