diff options
Diffstat (limited to 'MediaBrowser.Api/Images/ImageService.cs')
| -rw-r--r-- | MediaBrowser.Api/Images/ImageService.cs | 573 |
1 files changed, 0 insertions, 573 deletions
diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs deleted file mode 100644 index 55859d9f1..000000000 --- a/MediaBrowser.Api/Images/ImageService.cs +++ /dev/null @@ -1,573 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Drawing; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Services; -using Microsoft.Extensions.Logging; -using Microsoft.Net.Http.Headers; -using User = Jellyfin.Data.Entities.User; - -namespace MediaBrowser.Api.Images -{ - [Route("/Items/{Id}/Images/{Type}", "GET")] - [Route("/Items/{Id}/Images/{Type}/{Index}", "GET")] - [Route("/Items/{Id}/Images/{Type}", "HEAD")] - [Route("/Items/{Id}/Images/{Type}/{Index}", "HEAD")] - [Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}/{PercentPlayed}/{UnplayedCount}", "GET")] - [Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}/{PercentPlayed}/{UnplayedCount}", "HEAD")] - public class GetItemImage : ImageRequest - { - /// <summary> - /// Gets or sets the id. - /// </summary> - /// <value>The id.</value> - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path")] - public Guid Id { get; set; } - } - - /// <summary> - /// Class GetPersonImage. - /// </summary> - [Route("/Artists/{Name}/Images/{Type}", "GET")] - [Route("/Artists/{Name}/Images/{Type}/{Index}", "GET")] - [Route("/Genres/{Name}/Images/{Type}", "GET")] - [Route("/Genres/{Name}/Images/{Type}/{Index}", "GET")] - [Route("/MusicGenres/{Name}/Images/{Type}", "GET")] - [Route("/MusicGenres/{Name}/Images/{Type}/{Index}", "GET")] - [Route("/Persons/{Name}/Images/{Type}", "GET")] - [Route("/Persons/{Name}/Images/{Type}/{Index}", "GET")] - [Route("/Studios/{Name}/Images/{Type}", "GET")] - [Route("/Studios/{Name}/Images/{Type}/{Index}", "GET")] - ////[Route("/Years/{Year}/Images/{Type}", "GET")] - ////[Route("/Years/{Year}/Images/{Type}/{Index}", "GET")] - [Route("/Artists/{Name}/Images/{Type}", "HEAD")] - [Route("/Artists/{Name}/Images/{Type}/{Index}", "HEAD")] - [Route("/Genres/{Name}/Images/{Type}", "HEAD")] - [Route("/Genres/{Name}/Images/{Type}/{Index}", "HEAD")] - [Route("/MusicGenres/{Name}/Images/{Type}", "HEAD")] - [Route("/MusicGenres/{Name}/Images/{Type}/{Index}", "HEAD")] - [Route("/Persons/{Name}/Images/{Type}", "HEAD")] - [Route("/Persons/{Name}/Images/{Type}/{Index}", "HEAD")] - [Route("/Studios/{Name}/Images/{Type}", "HEAD")] - [Route("/Studios/{Name}/Images/{Type}/{Index}", "HEAD")] - ////[Route("/Years/{Year}/Images/{Type}", "HEAD")] - ////[Route("/Years/{Year}/Images/{Type}/{Index}", "HEAD")] - public class GetItemByNameImage : ImageRequest - { - /// <summary> - /// Gets or sets the name. - /// </summary> - /// <value>The name.</value> - [ApiMember(Name = "Name", Description = "Item name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Name { get; set; } - } - - /// <summary> - /// Class GetUserImage. - /// </summary> - [Route("/Users/{Id}/Images/{Type}", "GET")] - [Route("/Users/{Id}/Images/{Type}/{Index}", "GET")] - [Route("/Users/{Id}/Images/{Type}", "HEAD")] - [Route("/Users/{Id}/Images/{Type}/{Index}", "HEAD")] - public class GetUserImage : ImageRequest - { - /// <summary> - /// Gets or sets the id. - /// </summary> - /// <value>The id.</value> - [ApiMember(Name = "Id", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public Guid Id { get; set; } - } - - /// <summary> - /// Class ImageService. - /// </summary> - public class ImageService : BaseApiService - { - private readonly IUserManager _userManager; - - private readonly ILibraryManager _libraryManager; - - private readonly IProviderManager _providerManager; - - private readonly IImageProcessor _imageProcessor; - private readonly IFileSystem _fileSystem; - private readonly IAuthorizationContext _authContext; - - /// <summary> - /// Initializes a new instance of the <see cref="ImageService" /> class. - /// </summary> - public ImageService( - ILogger<ImageService> logger, - IServerConfigurationManager serverConfigurationManager, - IHttpResultFactory httpResultFactory, - IUserManager userManager, - ILibraryManager libraryManager, - IProviderManager providerManager, - IImageProcessor imageProcessor, - IFileSystem fileSystem, - IAuthorizationContext authContext) - : base(logger, serverConfigurationManager, httpResultFactory) - { - _userManager = userManager; - _libraryManager = libraryManager; - _providerManager = providerManager; - _imageProcessor = imageProcessor; - _fileSystem = fileSystem; - _authContext = authContext; - } - - /// <summary> - /// Gets the specified request. - /// </summary> - /// <param name="request">The request.</param> - /// <returns>System.Object.</returns> - public object Get(GetItemImage request) - { - return GetImage(request, request.Id, null, false); - } - - /// <summary> - /// Gets the specified request. - /// </summary> - /// <param name="request">The request.</param> - /// <returns>System.Object.</returns> - public object Head(GetItemImage request) - { - return GetImage(request, request.Id, null, true); - } - - /// <summary> - /// Gets the specified request. - /// </summary> - /// <param name="request">The request.</param> - /// <returns>System.Object.</returns> - public object Get(GetUserImage request) - { - var item = _userManager.GetUserById(request.Id); - - return GetImage(request, item, false); - } - - public object Head(GetUserImage request) - { - var item = _userManager.GetUserById(request.Id); - - return GetImage(request, item, true); - } - - public object Get(GetItemByNameImage request) - { - var type = GetPathValue(0).ToString(); - - var item = GetItemByName(request.Name, type, _libraryManager, new DtoOptions(false)); - - return GetImage(request, item.Id, item, false); - } - - public object Head(GetItemByNameImage request) - { - var type = GetPathValue(0).ToString(); - - var item = GetItemByName(request.Name, type, _libraryManager, new DtoOptions(false)); - - return GetImage(request, item.Id, item, true); - } - - /// <summary> - /// Gets the image. - /// </summary> - /// <param name="request">The request.</param> - /// <param name="item">The item.</param> - /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param> - /// <returns>System.Object.</returns> - /// <exception cref="ResourceNotFoundException"></exception> - public Task<object> GetImage(ImageRequest request, Guid itemId, BaseItem item, bool isHeadRequest) - { - if (request.PercentPlayed.HasValue) - { - if (request.PercentPlayed.Value <= 0) - { - request.PercentPlayed = null; - } - else if (request.PercentPlayed.Value >= 100) - { - request.PercentPlayed = null; - request.AddPlayedIndicator = true; - } - } - - if (request.PercentPlayed.HasValue) - { - request.UnplayedCount = null; - } - - if (request.UnplayedCount.HasValue - && request.UnplayedCount.Value <= 0) - { - request.UnplayedCount = null; - } - - if (item == null) - { - item = _libraryManager.GetItemById(itemId); - - if (item == null) - { - throw new ResourceNotFoundException(string.Format("Item {0} not found.", itemId.ToString("N", CultureInfo.InvariantCulture))); - } - } - - var imageInfo = GetImageInfo(request, item); - if (imageInfo == null) - { - throw new ResourceNotFoundException(string.Format("{0} does not have an image of type {1}", item.Name, request.Type)); - } - - bool cropWhitespace; - if (request.CropWhitespace.HasValue) - { - cropWhitespace = request.CropWhitespace.Value; - } - else - { - cropWhitespace = request.Type == ImageType.Logo || request.Type == ImageType.Art; - } - - var outputFormats = GetOutputFormats(request); - - TimeSpan? cacheDuration = null; - - if (!string.IsNullOrEmpty(request.Tag)) - { - cacheDuration = TimeSpan.FromDays(365); - } - - var responseHeaders = new Dictionary<string, string> - { - {"transferMode.dlna.org", "Interactive"}, - {"realTimeInfo.dlna.org", "DLNA.ORG_TLAG=*"} - }; - - return GetImageResult( - item, - itemId, - request, - imageInfo, - cropWhitespace, - outputFormats, - cacheDuration, - responseHeaders, - isHeadRequest); - } - - public Task<object> GetImage(ImageRequest request, User user, bool isHeadRequest) - { - var imageInfo = GetImageInfo(request, user); - - TimeSpan? cacheDuration = null; - - if (!string.IsNullOrEmpty(request.Tag)) - { - cacheDuration = TimeSpan.FromDays(365); - } - - var responseHeaders = new Dictionary<string, string> - { - {"transferMode.dlna.org", "Interactive"}, - {"realTimeInfo.dlna.org", "DLNA.ORG_TLAG=*"} - }; - - var outputFormats = GetOutputFormats(request); - - return GetImageResult(user.Id, - request, - imageInfo, - outputFormats, - cacheDuration, - responseHeaders, - isHeadRequest); - } - - private async Task<object> GetImageResult( - Guid itemId, - ImageRequest request, - ItemImageInfo info, - IReadOnlyCollection<ImageFormat> supportedFormats, - TimeSpan? cacheDuration, - IDictionary<string, string> headers, - bool isHeadRequest) - { - info.Type = ImageType.Profile; - var options = new ImageProcessingOptions - { - CropWhiteSpace = true, - Height = request.Height, - ImageIndex = request.Index ?? 0, - Image = info, - Item = null, // Hack alert - ItemId = itemId, - MaxHeight = request.MaxHeight, - MaxWidth = request.MaxWidth, - Quality = request.Quality ?? 100, - Width = request.Width, - AddPlayedIndicator = request.AddPlayedIndicator, - PercentPlayed = 0, - UnplayedCount = request.UnplayedCount, - Blur = request.Blur, - BackgroundColor = request.BackgroundColor, - ForegroundLayer = request.ForegroundLayer, - SupportedOutputFormats = supportedFormats - }; - - var imageResult = await _imageProcessor.ProcessImage(options).ConfigureAwait(false); - - headers[HeaderNames.Vary] = HeaderNames.Accept; - - return await ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions - { - CacheDuration = cacheDuration, - ResponseHeaders = headers, - ContentType = imageResult.Item2, - DateLastModified = imageResult.Item3, - IsHeadRequest = isHeadRequest, - Path = imageResult.Item1, - - FileShare = FileShare.Read - - }).ConfigureAwait(false); - } - - private async Task<object> GetImageResult( - BaseItem item, - Guid itemId, - ImageRequest request, - ItemImageInfo image, - bool cropwhitespace, - IReadOnlyCollection<ImageFormat> supportedFormats, - TimeSpan? cacheDuration, - IDictionary<string, string> headers, - bool isHeadRequest) - { - if (!image.IsLocalFile) - { - item ??= _libraryManager.GetItemById(itemId); - image = await _libraryManager.ConvertImageToLocal(item, image, request.Index ?? 0).ConfigureAwait(false); - } - - var options = new ImageProcessingOptions - { - CropWhiteSpace = cropwhitespace, - Height = request.Height, - ImageIndex = request.Index ?? 0, - Image = image, - Item = item, - ItemId = itemId, - MaxHeight = request.MaxHeight, - MaxWidth = request.MaxWidth, - Quality = request.Quality ?? 100, - Width = request.Width, - AddPlayedIndicator = request.AddPlayedIndicator, - PercentPlayed = request.PercentPlayed ?? 0, - UnplayedCount = request.UnplayedCount, - Blur = request.Blur, - BackgroundColor = request.BackgroundColor, - ForegroundLayer = request.ForegroundLayer, - SupportedOutputFormats = supportedFormats - }; - - var imageResult = await _imageProcessor.ProcessImage(options).ConfigureAwait(false); - - headers[HeaderNames.Vary] = HeaderNames.Accept; - - return await ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions - { - CacheDuration = cacheDuration, - ResponseHeaders = headers, - ContentType = imageResult.Item2, - DateLastModified = imageResult.Item3, - IsHeadRequest = isHeadRequest, - Path = imageResult.Item1, - - FileShare = FileShare.Read - }).ConfigureAwait(false); - } - - private ImageFormat[] GetOutputFormats(ImageRequest request) - { - if (!string.IsNullOrWhiteSpace(request.Format) - && Enum.TryParse(request.Format, true, out ImageFormat format)) - { - return new[] { format }; - } - - return GetClientSupportedFormats(); - } - - private ImageFormat[] GetClientSupportedFormats() - { - var supportedFormats = Request.AcceptTypes ?? Array.Empty<string>(); - if (supportedFormats.Length > 0) - { - for (int i = 0; i < supportedFormats.Length; i++) - { - int index = supportedFormats[i].IndexOf(';'); - if (index != -1) - { - supportedFormats[i] = supportedFormats[i].Substring(0, index); - } - } - } - - var acceptParam = Request.QueryString["accept"]; - - var supportsWebP = SupportsFormat(supportedFormats, acceptParam, "webp", false); - - if (!supportsWebP) - { - var userAgent = Request.UserAgent ?? string.Empty; - if (userAgent.IndexOf("crosswalk", StringComparison.OrdinalIgnoreCase) != -1 && - userAgent.IndexOf("android", StringComparison.OrdinalIgnoreCase) != -1) - { - supportsWebP = true; - } - } - - var formats = new List<ImageFormat>(4); - - if (supportsWebP) - { - formats.Add(ImageFormat.Webp); - } - - formats.Add(ImageFormat.Jpg); - formats.Add(ImageFormat.Png); - - if (SupportsFormat(supportedFormats, acceptParam, "gif", true)) - { - formats.Add(ImageFormat.Gif); - } - - return formats.ToArray(); - } - - private bool SupportsFormat(IEnumerable<string> requestAcceptTypes, string acceptParam, string format, bool acceptAll) - { - var mimeType = "image/" + format; - - if (requestAcceptTypes.Contains(mimeType)) - { - return true; - } - - if (acceptAll && requestAcceptTypes.Contains("*/*")) - { - return true; - } - - return string.Equals(Request.QueryString["accept"], format, StringComparison.OrdinalIgnoreCase); - } - - /// <summary> - /// Gets the image path. - /// </summary> - /// <param name="request">The request.</param> - /// <param name="item">The item.</param> - /// <returns>System.String.</returns> - private static ItemImageInfo GetImageInfo(ImageRequest request, BaseItem item) - { - var index = request.Index ?? 0; - - return item.GetImageInfo(request.Type, index); - } - - private static ItemImageInfo GetImageInfo(ImageRequest request, User user) - { - var info = new ItemImageInfo - { - Path = user.ProfileImage.Path, - Type = ImageType.Primary, - DateModified = user.ProfileImage.LastModified, - }; - - if (request.Width.HasValue) - { - info.Width = request.Width.Value; - } - - if (request.Height.HasValue) - { - info.Height = request.Height.Value; - } - - return info; - } - - /// <summary> - /// Posts the image. - /// </summary> - /// <param name="entity">The entity.</param> - /// <param name="inputStream">The input stream.</param> - /// <param name="imageType">Type of the image.</param> - /// <param name="mimeType">Type of the MIME.</param> - /// <returns>Task.</returns> - public async Task PostImage(BaseItem entity, Stream inputStream, ImageType imageType, string mimeType) - { - var memoryStream = await GetMemoryStream(inputStream); - - // Handle image/png; charset=utf-8 - mimeType = mimeType.Split(';').FirstOrDefault(); - - await _providerManager.SaveImage(entity, memoryStream, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false); - - entity.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); - } - - private static async Task<MemoryStream> GetMemoryStream(Stream inputStream) - { - using var reader = new StreamReader(inputStream); - var text = await reader.ReadToEndAsync().ConfigureAwait(false); - - var bytes = Convert.FromBase64String(text); - return new MemoryStream(bytes) - { - Position = 0 - }; - } - - private async Task PostImage(User user, Stream inputStream, string mimeType) - { - var memoryStream = await GetMemoryStream(inputStream); - - // Handle image/png; charset=utf-8 - mimeType = mimeType.Split(';').FirstOrDefault(); - var userDataPath = Path.Combine(ServerConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, user.Username); - if (user.ProfileImage != null) - { - _userManager.ClearProfileImage(user); - } - - user.ProfileImage = new Jellyfin.Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + MimeTypes.ToExtension(mimeType))); - - await _providerManager - .SaveImage(user, memoryStream, mimeType, user.ProfileImage.Path) - .ConfigureAwait(false); - await _userManager.UpdateUserAsync(user); - } - } -} |
