back photo + event tags and persons

This commit is contained in:
2025-08-10 20:07:40 +02:00
parent 0cc8bddfa1
commit f61b48fa4b
46 changed files with 1438 additions and 189 deletions

View File

@@ -0,0 +1,104 @@
using back.Options;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
namespace back.persistance.blob;
public class FileSystemImageStorageService(
IOptions<Databases> systemOptions,
IOptionsMonitor<DatabaseConfig> options,
IMemoryCache memoryCache
) : IBlobStorageService
{
private readonly string RootPath = systemOptions.Value.BaseDirectory ?? "";
private readonly DatabaseConfig config = options.Get(DatabaseConfig.BlobStorage);
private readonly IMemoryCache cache = memoryCache;
private string GetFullPath(string fileName)
{
// Ensure the directory exists
var directory = Path.Join(RootPath, config.SystemContainer, fileName);
if (directory != null && !Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
return fileName;
}
public async Task DeleteAsync(string fileName)
{
var path = GetFullPath(fileName);
if (cache.TryGetValue(path, out Stream cachedStream))
{
cachedStream.Dispose(); // Dispose the cached stream if it exists
cache.Remove(path); // Remove from cache
}
if (!File.Exists(path))
{
return; // No file to delete
}
try
{
File.Delete(path);
}
catch (Exception ex)
{
throw new InvalidOperationException($"Error deleting file {fileName}: {ex.Message}", ex);
}
}
public Task<Stream?> GetStreamAsync(string fileName)
{
var path = GetFullPath(fileName);
if (File.Exists(path))
{
if (cache.TryGetValue(path, out Stream? cachedStream))
{
return Task.FromResult<Stream?>(cachedStream);
}
// open the file stream for multiple reads and cache it for performance
var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
cache.CreateEntry(path)
.SetValue(fileStream)
.SetSlidingExpiration(TimeSpan.FromMinutes(30)); // Cache for 30 minutes
return Task.FromResult<Stream?>(fileStream);
}
return Task.FromResult<Stream?>(null);
}
public async Task<byte[]?> GetBytesAsync(string fileName)
{
var stream = await GetStreamAsync(fileName);
if (stream != null)
{
using var memoryStream = new MemoryStream();
await stream.CopyToAsync(memoryStream);
return memoryStream.ToArray();
}
return null;
}
public async Task SaveAsync(Stream blobStream, string fileName)
{
var path = GetFullPath(fileName);
if (cache.TryGetValue(path, out Stream? _) || File.Exists(path))
{
throw new InvalidOperationException($"File {fileName} already exists. Use Update for updating file info.");
}
using var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write);
await blobStream.CopyToAsync(fileStream);
}
public async Task UpdateAsync(Stream blobStream, string fileName)
{
var path = GetFullPath(fileName);
if (File.Exists(path))
{
await DeleteAsync(fileName);
}
await SaveAsync(blobStream, fileName);
}
}

View File

@@ -0,0 +1,11 @@
namespace back.persistance.blob;
public interface IBlobStorageService
{
Task SaveAsync(Stream blobStream, string fileName);
Task<Stream?> GetStreamAsync(string fileName);
Task<byte[]?> GetBytesAsync(string fileName);
Task DeleteAsync(string fileName);
Task UpdateAsync(Stream blobStream, string fileName);
}