Enhance ImageDownloader to improve error handling and logging
Updated the ImageDownloader class to include detailed logging for various failure scenarios during image download attempts. Added checks for invalid URLs, unsuccessful HTTP responses, and empty content responses, ensuring that all failures are logged with appropriate warnings. This enhancement improves the robustness of the image downloading process and provides better insights into potential issues.
This commit is contained in:
@@ -1,9 +1,18 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TeleWave.Application.Common.Interfaces;
|
||||
|
||||
namespace TeleWave.Infrastructure.Media;
|
||||
|
||||
/// <summary>Скачивает изображение по URL через HTTP-клиент «metadata» и определяет расширение.</summary>
|
||||
public sealed class ImageDownloader(IHttpClientFactory httpFactory) : IImageDownloader
|
||||
/// <summary>
|
||||
/// Скачивает изображение по URL через HTTP-клиент «metadata» и определяет расширение.
|
||||
///
|
||||
/// Любая неудача — это null, а не исключение: постер не тот повод, чтобы ронять применение
|
||||
/// метаданных. Но молчать о ней нельзя — снаружи «постера нет» неотличимо от «постера не было
|
||||
/// в источнике», а причина обычно сетевая: у TMDb картинки лежат на отдельном хосте
|
||||
/// (<c>image.tmdb.org</c>), и он бывает недоступен там, где сам API работает.
|
||||
/// </summary>
|
||||
public sealed class ImageDownloader(IHttpClientFactory httpFactory, ILogger<ImageDownloader> logger)
|
||||
: IImageDownloader
|
||||
{
|
||||
public async Task<DownloadedImage?> 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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user