Created download systems, for files.

This commit is contained in:
michael-bailey 2025-03-19 01:50:56 +00:00
parent f468af89e0
commit f311e14ec1
3 changed files with 82 additions and 39 deletions

View File

@ -114,4 +114,14 @@ public class FilesController(
return RedirectToAction("Index");
}
public async Task<IActionResult> Download(Guid id)
{
var filename = await fileRepository.GetFileName(id);
var stream = fileRepository.EnumerateFileContentsAsync(id);
return File(stream, "application/octet-stream", filename);
}
}

View File

@ -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<Guid?>)> _creationQueue = new();
private readonly Lock _countLock = new();
public async Task<List<FileHandle>> GetAllFilesAsync()
@ -23,60 +24,89 @@ public class FileRepository(ApplicationDbContext context)
.Include(e => e.FileBlocks).FirstAsync();
}
public Task<string> 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<Guid?> TryNewFileAsync(string name, Stream reader)
{
var tcs = new TaskCompletionSource<Guid?>();
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<Guid?> 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<FileHandle> CreateFileBlocks(Stream reader, FileHandle fileHandle)
{
var blockNumber = 0;
var blocks = new List<FileBlock>();
var buffer = new byte[1024];
while (await reader.ReadAsync(buffer) > 0)

View File

@ -54,6 +54,9 @@
<a
asp-controller="Files" asp-action="Index" asp-route-id="@file.Id"
class="btn btn-primary me-2">View...</a>
<a
asp-controller="Files" asp-action="Download" asp-route-id="@file.Id"
class="btn btn-success me-2">Download</a>
<a
asp-controller="Files" asp-action="ConfirmDelete" asp-route-id="@file.Id"
class="btn btn-danger">Delete...</a>