diff --git a/Jellyfin.Api/Controllers/DlnaServerController.cs b/Jellyfin.Api/Controllers/DlnaServerController.cs index 4e8c01577e..b1c576c330 100644 --- a/Jellyfin.Api/Controllers/DlnaServerController.cs +++ b/Jellyfin.Api/Controllers/DlnaServerController.cs @@ -9,6 +9,7 @@ using Emby.Dlna.Main; using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using MediaBrowser.Controller.Dlna; +using MediaBrowser.Model.Net; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; @@ -337,11 +338,7 @@ namespace Jellyfin.Api.Controllers return NotFound(); } - var contentType = "image/" + Path.GetExtension(fileName) - .TrimStart('.') - .ToLowerInvariant(); - - return File(icon.Stream, contentType); + return File(icon.Stream, MimeTypes.GetMimeType(fileName)); } private string GetAbsoluteUri() diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 86933074d0..e72589cfae 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -1878,8 +1878,8 @@ namespace Jellyfin.Api.Controllers if (!supportsWebP) { var userAgent = Request.Headers[HeaderNames.UserAgent].ToString(); - if (userAgent.IndexOf("crosswalk", StringComparison.OrdinalIgnoreCase) != -1 && - userAgent.IndexOf("android", StringComparison.OrdinalIgnoreCase) != -1) + if (userAgent.Contains("crosswalk", StringComparison.OrdinalIgnoreCase) + && userAgent.Contains("android", StringComparison.OrdinalIgnoreCase)) { supportsWebP = true; } @@ -1905,10 +1905,7 @@ namespace Jellyfin.Api.Controllers private bool SupportsFormat(IReadOnlyCollection requestAcceptTypes, string acceptParam, ImageFormat format, bool acceptAll) { - var normalized = format.ToString().ToLowerInvariant(); - var mimeType = "image/" + normalized; - - if (requestAcceptTypes.Contains(mimeType)) + if (requestAcceptTypes.Contains(format.GetMimeType())) { return true; } @@ -1918,6 +1915,8 @@ namespace Jellyfin.Api.Controllers return true; } + // Review if this should be jpeg, jpg or both for ImageFormat.Jpg + var normalized = format.ToString().ToLowerInvariant(); return string.Equals(acceptParam, normalized, StringComparison.OrdinalIgnoreCase); } diff --git a/MediaBrowser.Model/Drawing/ImageFormatExtensions.cs b/MediaBrowser.Model/Drawing/ImageFormatExtensions.cs new file mode 100644 index 0000000000..68a5c25345 --- /dev/null +++ b/MediaBrowser.Model/Drawing/ImageFormatExtensions.cs @@ -0,0 +1,27 @@ +using System.ComponentModel; +using System.Net.Mime; + +namespace MediaBrowser.Model.Drawing; + +/// +/// Extension class for the enum. +/// +public static class ImageFormatExtensions +{ + /// + /// Returns the correct mime type for this . + /// + /// This . + /// The is an invalid enumeration value. + /// The correct mime type for this . + public static string GetMimeType(this ImageFormat format) + => format switch + { + ImageFormat.Bmp => "image/bmp", + ImageFormat.Gif => MediaTypeNames.Image.Gif, + ImageFormat.Jpg => MediaTypeNames.Image.Jpeg, + ImageFormat.Png => "image/png", + ImageFormat.Webp => "image/webp", + _ => throw new InvalidEnumArgumentException(nameof(format), (int)format, typeof(ImageFormat)) + }; +} diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index ee8451853d..3b03466e9d 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -116,7 +116,6 @@ namespace MediaBrowser.Model.Net { "audio/x-wavpack", ".wv" }, // Type image - { "image/jpg", ".jpg" }, { "image/jpeg", ".jpg" }, { "image/x-png", ".png" }, diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index b1d73c4c41..0d1bdec585 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -14,6 +14,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; @@ -172,7 +173,13 @@ namespace MediaBrowser.Providers.Manager if (response.HasImage) { - if (!string.IsNullOrEmpty(response.Path)) + if (string.IsNullOrEmpty(response.Path)) + { + var mimeType = response.Format.GetMimeType(); + + await _providerManager.SaveImage(item, response.Stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false); + } + else { if (response.Protocol == MediaProtocol.Http) { @@ -195,12 +202,6 @@ namespace MediaBrowser.Providers.Manager await _providerManager.SaveImage(item, stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false); } } - else - { - var mimeType = "image/" + response.Format.ToString().ToLowerInvariant(); - - await _providerManager.SaveImage(item, response.Stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false); - } downloadedImages.Add(imageType); result.UpdateType |= ItemUpdateType.ImageUpdate; diff --git a/tests/Jellyfin.Model.Tests/Drawing/ImageFormatExtensionsTests.cs b/tests/Jellyfin.Model.Tests/Drawing/ImageFormatExtensionsTests.cs new file mode 100644 index 0000000000..7c3a7ff6c7 --- /dev/null +++ b/tests/Jellyfin.Model.Tests/Drawing/ImageFormatExtensionsTests.cs @@ -0,0 +1,33 @@ +using System; +using System.ComponentModel; +using MediaBrowser.Model.Drawing; +using Xunit; + +namespace Jellyfin.Model.Drawing; + +public static class ImageFormatExtensionsTests +{ + private static TheoryData GetAllImageFormats() + { + var theoryTypes = new TheoryData(); + foreach (var x in Enum.GetValues()) + { + theoryTypes.Add(x); + } + + return theoryTypes; + } + + [Theory] + [MemberData(nameof(GetAllImageFormats))] + public static void GetMimeType_Valid_Valid(ImageFormat format) + => Assert.Null(Record.Exception(() => format.GetMimeType())); + + [Theory] + [InlineData((ImageFormat)int.MinValue)] + [InlineData((ImageFormat)int.MaxValue)] + [InlineData((ImageFormat)(-1))] + [InlineData((ImageFormat)5)] + public static void GetMimeType_Valid_ThrowsInvalidEnumArgumentException(ImageFormat format) + => Assert.Throws(() => format.GetMimeType()); +} diff --git a/tests/Jellyfin.Model.Tests/Net/MimeTypesTests.cs b/tests/Jellyfin.Model.Tests/Net/MimeTypesTests.cs index 7b50c54b0d..cbab455f01 100644 --- a/tests/Jellyfin.Model.Tests/Net/MimeTypesTests.cs +++ b/tests/Jellyfin.Model.Tests/Net/MimeTypesTests.cs @@ -124,7 +124,6 @@ namespace Jellyfin.Model.Tests.Net [InlineData("font/woff2", ".woff2")] [InlineData("image/bmp", ".bmp")] [InlineData("image/gif", ".gif")] - [InlineData("image/jpg", ".jpg")] [InlineData("image/jpeg", ".jpg")] [InlineData("image/png", ".png")] [InlineData("image/svg+xml", ".svg")]