diff --git a/backend/src/TeleWave.Infrastructure/Media/ImageDownloader.cs b/backend/src/TeleWave.Infrastructure/Media/ImageDownloader.cs
index 1c2b90c..aa41fa5 100644
--- a/backend/src/TeleWave.Infrastructure/Media/ImageDownloader.cs
+++ b/backend/src/TeleWave.Infrastructure/Media/ImageDownloader.cs
@@ -1,9 +1,18 @@
+using Microsoft.Extensions.Logging;
using TeleWave.Application.Common.Interfaces;
namespace TeleWave.Infrastructure.Media;
-/// Скачивает изображение по URL через HTTP-клиент «metadata» и определяет расширение.
-public sealed class ImageDownloader(IHttpClientFactory httpFactory) : IImageDownloader
+///
+/// Скачивает изображение по URL через HTTP-клиент «metadata» и определяет расширение.
+///
+/// Любая неудача — это null, а не исключение: постер не тот повод, чтобы ронять применение
+/// метаданных. Но молчать о ней нельзя — снаружи «постера нет» неотличимо от «постера не было
+/// в источнике», а причина обычно сетевая: у TMDb картинки лежат на отдельном хосте
+/// (image.tmdb.org), и он бывает недоступен там, где сам API работает.
+///
+public sealed class ImageDownloader(IHttpClientFactory httpFactory, ILogger logger)
+ : IImageDownloader
{
public async Task DownloadAsync(
string url,
@@ -17,22 +26,40 @@ public sealed class ImageDownloader(IHttpClientFactory httpFactory) : IImageDown
!Uri.TryCreate(url, UriKind.Absolute, out var uri)
|| (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps)
)
+ {
+ logger.LogWarning("Картинка не скачана: недопустимый адрес {Url}", url);
return null;
+ }
try
{
var client = httpFactory.CreateClient("metadata");
using var response = await client.GetAsync(uri, cancellationToken);
if (!response.IsSuccessStatusCode)
+ {
+ logger.LogWarning(
+ "Картинка не скачана: {Url} ответил {Status}",
+ url,
+ (int)response.StatusCode
+ );
return null;
+ }
var ext = ExtensionFor(url, response.Content.Headers.ContentType?.MediaType);
var bytes = await response.Content.ReadAsByteArrayAsync(cancellationToken);
- return bytes.Length == 0 ? null : new DownloadedImage(bytes, ext);
+ if (bytes.Length == 0)
+ {
+ logger.LogWarning("Картинка не скачана: {Url} вернул пустой ответ", url);
+ return null;
+ }
+
+ return new DownloadedImage(bytes, ext);
}
catch (Exception ex)
when (ex is HttpRequestException or TaskCanceledException or IOException)
{
+ // Самая частая причина — недоступный хост картинок: он отдельный от хоста API.
+ logger.LogWarning(ex, "Картинка не скачана: {Url} недоступен", url);
return null;
}
}