VideoAttachmentsController.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. using System;
  2. using System.ComponentModel.DataAnnotations;
  3. using System.Net.Mime;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6. using Jellyfin.Api.Attributes;
  7. using Jellyfin.Api.Extensions;
  8. using Jellyfin.Api.Helpers;
  9. using MediaBrowser.Common.Extensions;
  10. using MediaBrowser.Controller.Entities;
  11. using MediaBrowser.Controller.Library;
  12. using MediaBrowser.Controller.MediaEncoding;
  13. using Microsoft.AspNetCore.Http;
  14. using Microsoft.AspNetCore.Mvc;
  15. namespace Jellyfin.Api.Controllers;
  16. /// <summary>
  17. /// Attachments controller.
  18. /// </summary>
  19. [Route("Videos")]
  20. public class VideoAttachmentsController : BaseJellyfinApiController
  21. {
  22. private readonly ILibraryManager _libraryManager;
  23. private readonly IAttachmentExtractor _attachmentExtractor;
  24. /// <summary>
  25. /// Initializes a new instance of the <see cref="VideoAttachmentsController"/> class.
  26. /// </summary>
  27. /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
  28. /// <param name="attachmentExtractor">Instance of the <see cref="IAttachmentExtractor"/> interface.</param>
  29. public VideoAttachmentsController(
  30. ILibraryManager libraryManager,
  31. IAttachmentExtractor attachmentExtractor)
  32. {
  33. _libraryManager = libraryManager;
  34. _attachmentExtractor = attachmentExtractor;
  35. }
  36. /// <summary>
  37. /// Get video attachment.
  38. /// </summary>
  39. /// <param name="videoId">Video ID.</param>
  40. /// <param name="mediaSourceId">Media Source ID.</param>
  41. /// <param name="index">Attachment Index.</param>
  42. /// <response code="200">Attachment retrieved.</response>
  43. /// <response code="404">Video or attachment not found.</response>
  44. /// <returns>An <see cref="FileStreamResult"/> containing the attachment stream on success, or a <see cref="NotFoundResult"/> if the attachment could not be found.</returns>
  45. [HttpGet("{videoId}/{mediaSourceId}/Attachments/{index}")]
  46. [ProducesFile(MediaTypeNames.Application.Octet)]
  47. [ProducesResponseType(StatusCodes.Status200OK)]
  48. [ProducesResponseType(StatusCodes.Status404NotFound)]
  49. public async Task<ActionResult> GetAttachment(
  50. [FromRoute, Required] Guid videoId,
  51. [FromRoute, Required] string mediaSourceId,
  52. [FromRoute, Required] int index)
  53. {
  54. try
  55. {
  56. var item = _libraryManager.GetItemById<BaseItem>(videoId, User.GetUserId());
  57. if (item is null)
  58. {
  59. return NotFound();
  60. }
  61. var (attachment, stream) = await _attachmentExtractor.GetAttachment(
  62. item,
  63. mediaSourceId,
  64. index,
  65. CancellationToken.None)
  66. .ConfigureAwait(false);
  67. var contentType = string.IsNullOrWhiteSpace(attachment.MimeType)
  68. ? MediaTypeNames.Application.Octet
  69. : attachment.MimeType;
  70. return new FileStreamResult(stream, contentType);
  71. }
  72. catch (ResourceNotFoundException e)
  73. {
  74. return NotFound(e.Message);
  75. }
  76. }
  77. }