diff --git a/Jellyfin.Api/Controllers/AttachmentsController.cs b/Jellyfin.Api/Controllers/AttachmentsController.cs new file mode 100644 index 0000000000..5d48a79b9b --- /dev/null +++ b/Jellyfin.Api/Controllers/AttachmentsController.cs @@ -0,0 +1,86 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Controller.Net; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace Jellyfin.Api.Controllers +{ + /// + /// Attachments controller. + /// + [Route("Videos")] + [Authenticated] + public class AttachmentsController : Controller + { + private readonly ILibraryManager _libraryManager; + private readonly IAttachmentExtractor _attachmentExtractor; + + /// + /// Initializes a new instance of the class. + /// + /// Instance of the interface. + /// Instance of the interface. + public AttachmentsController( + ILibraryManager libraryManager, + IAttachmentExtractor attachmentExtractor) + { + _libraryManager = libraryManager; + _attachmentExtractor = attachmentExtractor; + } + + /// + /// Get video attachment. + /// + /// Video ID. + /// Media Source ID. + /// Attachment Index. + /// Attachment. + [HttpGet("{VideoID}/{MediaSourceID}/Attachments/{Index}")] + [Produces("application/octet-stream")] + [ProducesResponseType(typeof(FileStreamResult), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(string), StatusCodes.Status500InternalServerError)] + public async Task GetAttachment( + [FromRoute] Guid videoId, + [FromRoute] string mediaSourceId, + [FromRoute] int index) + { + try + { + var item = _libraryManager.GetItemById(videoId); + if (item == null) + { + return NotFound(); + } + + var (attachment, stream) = await _attachmentExtractor.GetAttachment( + item, + mediaSourceId, + index, + CancellationToken.None) + .ConfigureAwait(false); + + var contentType = "application/octet-stream"; + if (string.IsNullOrWhiteSpace(attachment.MimeType)) + { + contentType = attachment.MimeType; + } + + return new FileStreamResult(stream, contentType); + } + catch (ResourceNotFoundException e) + { + return StatusCode(StatusCodes.Status404NotFound, e.Message); + } + catch (Exception e) + { + return StatusCode(StatusCodes.Status500InternalServerError, e.Message); + } + } + } +} diff --git a/MediaBrowser.Api/Attachments/AttachmentService.cs b/MediaBrowser.Api/Attachments/AttachmentService.cs deleted file mode 100644 index 1632ca1b06..0000000000 --- a/MediaBrowser.Api/Attachments/AttachmentService.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Services; -using Microsoft.Extensions.Logging; - -namespace MediaBrowser.Api.Attachments -{ - [Route("/Videos/{Id}/{MediaSourceId}/Attachments/{Index}", "GET", Summary = "Gets specified attachment.")] - public class GetAttachment - { - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public Guid Id { get; set; } - - [ApiMember(Name = "MediaSourceId", Description = "MediaSourceId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string MediaSourceId { get; set; } - - [ApiMember(Name = "Index", Description = "The attachment stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")] - public int Index { get; set; } - } - - public class AttachmentService : BaseApiService - { - private readonly ILibraryManager _libraryManager; - private readonly IAttachmentExtractor _attachmentExtractor; - - public AttachmentService( - ILogger logger, - IServerConfigurationManager serverConfigurationManager, - IHttpResultFactory httpResultFactory, - ILibraryManager libraryManager, - IAttachmentExtractor attachmentExtractor) - : base(logger, serverConfigurationManager, httpResultFactory) - { - _libraryManager = libraryManager; - _attachmentExtractor = attachmentExtractor; - } - - public async Task Get(GetAttachment request) - { - var (attachment, attachmentStream) = await GetAttachment(request).ConfigureAwait(false); - var mime = string.IsNullOrWhiteSpace(attachment.MimeType) ? "application/octet-stream" : attachment.MimeType; - - return ResultFactory.GetResult(Request, attachmentStream, mime); - } - - private Task<(MediaAttachment, Stream)> GetAttachment(GetAttachment request) - { - var item = _libraryManager.GetItemById(request.Id); - - return _attachmentExtractor.GetAttachment(item, - request.MediaSourceId, - request.Index, - CancellationToken.None); - } - } -} diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 0d62cf8c59..5ca74d4238 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -9,6 +9,10 @@ + + + + netstandard2.1 false