diff --git a/FileStorageService.www/Controllers/FilesController.cs b/FileStorageService.www/Controllers/FilesController.cs index 0e4645e..e4f7afa 100644 --- a/FileStorageService.www/Controllers/FilesController.cs +++ b/FileStorageService.www/Controllers/FilesController.cs @@ -114,4 +114,14 @@ public class FilesController( return RedirectToAction("Index"); } + + public async Task Download(Guid id) + { + + var filename = await fileRepository.GetFileName(id); + + var stream = fileRepository.EnumerateFileContentsAsync(id); + + return File(stream, "application/octet-stream", filename); + } } \ No newline at end of file diff --git a/FileStorageService.www/Repositories/FileRepository.cs b/FileStorageService.www/Repositories/FileRepository.cs index e342352..eaf5a49 100644 --- a/FileStorageService.www/Repositories/FileRepository.cs +++ b/FileStorageService.www/Repositories/FileRepository.cs @@ -1,3 +1,4 @@ +using System.Security.Cryptography.X509Certificates; using FileStorageService.www.Data; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -8,7 +9,7 @@ public class FileRepository(ApplicationDbContext context) { public static readonly int MAX_BLOCKS = 10_485_760; - private readonly Queue<(string, Stream)> _creationQueue = new(); + private readonly Queue<(string, Stream, TaskCompletionSource)> _creationQueue = new(); private readonly Lock _countLock = new(); public async Task> GetAllFilesAsync() @@ -23,60 +24,89 @@ public class FileRepository(ApplicationDbContext context) .Include(e => e.FileBlocks).FirstAsync(); } + public Task GetFileName(Guid id) + { + return (from handle in context.FileHandles + where handle.Id == id + select handle.Name).FirstAsync(); + } + + public Stream EnumerateFileContentsAsync(Guid id) + { + + var memoryStream = new MemoryStream(); + var writer = new BinaryWriter(memoryStream); + + var query = (from block in context.FileBlocks + where block.FileHandle.Id == id + orderby block.BlockNumber + select block.Data); + + foreach (var bytes in query.AsEnumerable()) + { + writer.Write(bytes); + writer.Flush(); + } + + memoryStream.Position = 0; + + return memoryStream; + } + public Task TryNewFileAsync(string name, Stream reader) { var tcs = new TaskCompletionSource(); lock (_creationQueue) { - _creationQueue.Enqueue((name, reader)); + _creationQueue.Enqueue((name, reader, tcs)); } - Task.Run(async () => - { - - Stream stream; - string name; - - lock (_creationQueue) - { - (name, stream) = _creationQueue.Dequeue(); - } - - var fileHandle = new FileHandle - { - Name = name - }; - - var handle = await CreateFileBlocks(stream, fileHandle); - var currentFileCount = handle.FileBlocks.Count(); - handle.FileBlockCount = currentFileCount; - - lock (_countLock) - { - var count = context.FileBlocks.Count(); - - if (count+currentFileCount > MAX_BLOCKS) - { - tcs.SetResult(null); - return; - } - - context.Add(fileHandle); - context.SaveChangesAsync(); - - tcs.SetResult(fileHandle.Id); - } - }); + Task.Run(async () => await StartProcessFileUpload()); return tcs.Task; } + private async Task StartProcessFileUpload() + { + Stream stream; + string name; + TaskCompletionSource tcs; + + lock (_creationQueue) + { + (name, stream, tcs) = _creationQueue.Dequeue(); + } + + var fileHandle = new FileHandle + { + Name = name + }; + + var handle = await CreateFileBlocks(stream, fileHandle); + var currentFileCount = handle.FileBlocks.Count(); + handle.FileBlockCount = currentFileCount; + + lock (_countLock) + { + var count = context.FileBlocks.Count(); + + if (count+currentFileCount > MAX_BLOCKS) + { + tcs.SetResult(null); + return; + } + + context.Add(fileHandle); + context.SaveChangesAsync(); + + tcs.SetResult(fileHandle.Id); + } + } private async Task CreateFileBlocks(Stream reader, FileHandle fileHandle) { var blockNumber = 0; - var blocks = new List(); var buffer = new byte[1024]; while (await reader.ReadAsync(buffer) > 0) diff --git a/FileStorageService.www/Views/Files/Index.cshtml b/FileStorageService.www/Views/Files/Index.cshtml index 32cdc40..156d78d 100644 --- a/FileStorageService.www/Views/Files/Index.cshtml +++ b/FileStorageService.www/Views/Files/Index.cshtml @@ -54,6 +54,9 @@ View... + Download Delete...