Files
trakqr/src/TrackApi/TrackQrApi/Features/Assets/Services/AssetStorageService.cs

84 lines
2.8 KiB
C#

namespace TrackQrApi.Features.Assets.Services;
public interface IAssetStorageService
{
Task<string> StoreAsync(Stream stream, string filename, string contentType);
Task<(Stream Stream, string ContentType)?> GetAsync(string storageKey);
Task DeleteAsync(string storageKey);
string GetPublicUrl(string storageKey, HttpContext context);
}
public class LocalAssetStorageService : IAssetStorageService
{
private readonly string _basePath;
private readonly ILogger<LocalAssetStorageService> _logger;
public LocalAssetStorageService(IConfiguration configuration, ILogger<LocalAssetStorageService> logger)
{
_logger = logger;
_basePath = configuration["Storage:LocalPath"] ?? Path.Combine(Directory.GetCurrentDirectory(), "uploads");
// Ensure directory exists
if (!Directory.Exists(_basePath)) Directory.CreateDirectory(_basePath);
}
public async Task<string> StoreAsync(Stream stream, string filename, string contentType)
{
// Generate unique storage key
var extension = Path.GetExtension(filename);
var storageKey = $"{Guid.NewGuid()}{extension}";
var filePath = Path.Combine(_basePath, storageKey);
await using var fileStream = new FileStream(filePath, FileMode.Create);
await stream.CopyToAsync(fileStream);
_logger.LogDebug("Stored asset at {FilePath}", filePath);
return storageKey;
}
public Task<(Stream Stream, string ContentType)?> GetAsync(string storageKey)
{
var filePath = Path.Combine(_basePath, storageKey);
if (!File.Exists(filePath)) return Task.FromResult<(Stream, string)?>(null);
var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
var contentType = GetContentType(storageKey);
return Task.FromResult<(Stream, string)?>((stream, contentType));
}
public Task DeleteAsync(string storageKey)
{
var filePath = Path.Combine(_basePath, storageKey);
if (File.Exists(filePath))
{
File.Delete(filePath);
_logger.LogDebug("Deleted asset at {FilePath}", filePath);
}
return Task.CompletedTask;
}
public string GetPublicUrl(string storageKey, HttpContext context)
{
var baseUrl = $"{context.Request.Scheme}://{context.Request.Host}";
return $"{baseUrl}/assets/{storageKey}";
}
private static string GetContentType(string filename)
{
var extension = Path.GetExtension(filename).ToLowerInvariant();
return extension switch
{
".png" => "image/png",
".jpg" or ".jpeg" => "image/jpeg",
".gif" => "image/gif",
".webp" => "image/webp",
".svg" => "image/svg+xml",
_ => "application/octet-stream"
};
}
}