LANCommander/LANCommander.Server/Endpoints/UploadEndpoints.cs

94 lines
3 KiB
C#
Raw Permalink Normal View History

2025-11-21 01:28:37 -06:00
using LANCommander.Server.Data.Models;
using LANCommander.Server.Models;
using LANCommander.Server.Services;
using Microsoft.AspNetCore.Mvc;
using ZiggyCreatures.Caching.Fusion;
namespace LANCommander.Server.Endpoints;
public static class UploadEndpoints
{
public static void MapUploadEndpoints(this IEndpointRouteBuilder routes)
{
var group = routes.MapGroup("/api/Upload").RequireAuthorization(RoleService.AdministratorRoleName);
2025-11-21 01:28:37 -06:00
group.MapPost("/Init", InitAsync);
2025-11-21 12:06:14 -06:00
group.MapPost("/Chunk", ChunkAsync).DisableAntiforgery();
2025-11-21 01:28:37 -06:00
}
internal static async Task<IResult> InitAsync(
SDK.Models.UploadInitRequest? request,
2025-11-21 01:28:37 -06:00
[FromServices] StorageLocationService storageLocationService,
[FromServices] ArchiveService archiveService,
[FromServices] IFusionCache cache)
{
var storageLocationId = request?.StorageLocationId;
var storageLocation = await storageLocationService.GetOrDefaultAsync(
storageLocationId == null || storageLocationId == Guid.Empty ? null : storageLocationId,
SDK.Enums.StorageLocationType.Archive);
2025-11-21 01:28:37 -06:00
if (!Directory.Exists(storageLocation.Path))
Directory.CreateDirectory(storageLocation.Path);
var archive = new Archive
{
ObjectKey = Guid.NewGuid().ToString(),
StorageLocationId = storageLocation.Id,
Version = ""
};
archive = await archiveService.AddAsync(archive);
var archivePath = await archiveService.GetArchiveFileLocationAsync(archive);
await cache.SetAsync($"ChunkArchivePath/{archive.ObjectKey}", archivePath, TimeSpan.FromHours(6));
2026-01-03 18:31:51 -06:00
var archiveDirectory = Path.GetDirectoryName(archivePath);
if (!string.IsNullOrEmpty(archiveDirectory) && !Directory.Exists(archiveDirectory))
Directory.CreateDirectory(archiveDirectory);
2025-11-21 01:28:37 -06:00
if (!File.Exists(archivePath))
File.Create(archivePath).Close();
else
File.Delete(archivePath);
return TypedResults.Ok(new { Key = Guid.Parse(archive.ObjectKey) });
2025-11-21 01:28:37 -06:00
}
internal static async Task<IResult> ChunkAsync(
2026-06-04 22:03:18 -05:00
[FromForm] long Start,
[FromForm] long End,
[FromForm] long Total,
[FromForm] Guid Key,
IFormFile File,
2025-11-21 01:28:37 -06:00
[FromServices] IFusionCache cache)
{
2026-06-04 22:03:18 -05:00
var filePath = await cache.GetOrDefaultAsync($"ChunkArchivePath/{Key}", string.Empty);
2025-11-21 01:28:37 -06:00
2026-06-04 22:03:18 -05:00
if (!System.IO.File.Exists(filePath))
2025-11-21 01:28:37 -06:00
return TypedResults.BadRequest("Destination file not initialized.");
using (var ms = new MemoryStream())
{
2026-06-04 22:03:18 -05:00
await File.CopyToAsync(ms);
2025-11-21 01:28:37 -06:00
var data = ms.ToArray();
using (var fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
2025-11-21 01:28:37 -06:00
{
2026-06-04 22:03:18 -05:00
fs.Position = Start;
2025-11-21 01:28:37 -06:00
fs.Write(data, 0, data.Length);
}
}
2026-06-04 22:03:18 -05:00
if (End == Total)
await cache.ExpireAsync($"ChunkArchivePath/{Key}");
2025-11-21 01:28:37 -06:00
return TypedResults.Ok();
}
}