84 lines
2.8 KiB
C#
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"
|
|
};
|
|
}
|
|
} |