Files
Govor/Govor.API/Controllers/MediaController.cs
T

127 lines
3.8 KiB
C#

using Govor.Application.Interfaces.Infrastructure.Extensions;
using Govor.Application.Interfaces.Medias;
using Govor.Contracts.Requests;
using Govor.Core.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Govor.API.Controllers;
[ApiController]
[Route("api/media")]
[Authorize(Roles = "User,Admin")]
public class MediaController : Controller
{
private readonly ILogger<MediaController> _logger;
private readonly IMediaService _mediaService;
private readonly IAccesserToDownloadMedia _accesser;
private readonly ICurrentUserService _currentUserService;
public MediaController(
ILogger<MediaController> logger,
IMediaService mediaService,
IAccesserToDownloadMedia accesser,
ICurrentUserService currentUserService)
{
_logger = logger;
_accesser = accesser;
_mediaService = mediaService;
_currentUserService = currentUserService;
}
[HttpPost("upload")]
[RequestSizeLimit(20_000_000)] // ~20MB
public async Task<IActionResult> Upload([FromForm] MediaUploadRequest request)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
if (request?.FromFile is null || request.FromFile.Length == 0)
return BadRequest("No file uploaded");
if (request.FromFile.Length > 20_000_000)
return BadRequest("File is too large");
if (string.IsNullOrWhiteSpace(request.MimeType))
return BadRequest("Missing MIME type");
try
{
byte[] fileBytes = await ReadFileAsync(request.FromFile);
var media = new Media(
_currentUserService.GetCurrentUserId(),
DateTime.UtcNow,
Path.GetFileName(request.FromFile.FileName),
fileBytes,
request.Type,
request.MimeType,
request.EncryptedKey,
request.OwnerType,
null)
{
OwnerType = request.OwnerType,
OwnerId = request.OwnerType == MediaOwnerType.Avatar
? _currentUserService.GetCurrentUserId()
: null,
};
var result = await _mediaService.UploadMediaAsync(media);
_logger.LogInformation("Uploaded file {FileName} from user {UserId}",
media.FileName, media.UploaderId);
return Ok(result);
}
catch (UnauthorizedAccessException ex)
{
_logger.LogWarning(ex, ex.Message);
return Forbid(ex.Message);
}
catch (InvalidOperationException ex)
{
_logger.LogWarning(ex, ex.Message);
return BadRequest(ex.Message);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error uploading media");
return StatusCode(500, "Internal server error");
}
}
private async Task<byte[]> ReadFileAsync(IFormFile file)
{
await using var ms = new MemoryStream();
await file.CopyToAsync(ms);
return ms.ToArray();
}
[HttpGet("download/{id}")]
public async Task<IActionResult> Download(Guid id)
{
try
{
var userId = _currentUserService.GetCurrentUserId();
if (!await _accesser.HasAccessAsync(id, userId))
return Forbid();
var media = await _mediaService.GetMediaByIdAsync(id);
return File(media.Data, media.MimeType, Path.GetFileName(media.FileName));
}
catch (KeyNotFoundException ex)
{
_logger.LogWarning(ex, ex.Message);
return NotFound("Media not found");
}
catch (Exception ex)
{
_logger.LogError(ex, "Error downloading media");
return StatusCode(500, "Internal server error");
}
}
}