Files
mws.backend.dotnet/infrastructure/Storage/S3DocumentContentStore.cs
T

82 lines
2.4 KiB
C#
Raw Normal View History

2026-09-15 21:13:37 +07:00
using System.Net;
using Amazon.S3;
using Amazon.S3.Model;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using mws.backend.dotnet.application.Common;
using mws.backend.dotnet.application.Documents;
namespace mws.backend.dotnet.infrastructure.Storage;
public class S3DocumentContentStore(
IAmazonS3 s3,
IOptions<MinioOptions> opt,
ILogger<S3DocumentContentStore> log) : IDocumentContentStore
{
private string Bucket => opt.Value.Bucket;
2026-09-15 22:23:54 +07:00
public static string FileNameNow(string name)
2026-09-15 21:13:37 +07:00
{
2026-09-15 22:23:54 +07:00
var slug = new string(name.Trim().ToLowerInvariant()
.Select(c => char.IsLetterOrDigit(c) ? c : '-')
.ToArray()).Trim('-');
if (slug.Length == 0)
{
slug = "document";
}
return $"{slug}_{DateTime.UtcNow:yyyyMMddHHmmss}";
}
public async Task<string> UploadAsync(Guid projectId, string fileName, string contentType, Stream body, CancellationToken ct)
{
var key = $"{projectId:N}/{FileNameNow(fileName)}.html";
2026-09-15 21:13:37 +07:00
try
{
await s3.PutObjectAsync(new PutObjectRequest
{
BucketName = Bucket,
2026-09-15 22:23:54 +07:00
Key = key,
2026-09-15 21:13:37 +07:00
InputStream = body,
ContentType = contentType,
AutoCloseStream = false,
}, ct);
2026-09-15 22:23:54 +07:00
return key;
2026-09-15 21:13:37 +07:00
}
catch (AmazonS3Exception ex)
{
2026-09-15 22:23:54 +07:00
log.LogError(ex, "MinIO upload failed for {Key}", key);
2026-09-15 21:13:37 +07:00
throw new StorageUnavailableException("Document upload failed", ex);
}
}
2026-09-15 22:23:54 +07:00
public async Task<Stream> DownloadAsync(string storageKey, CancellationToken ct)
2026-09-15 21:13:37 +07:00
{
try
{
2026-09-15 22:23:54 +07:00
var response = await s3.GetObjectAsync(Bucket, storageKey, ct);
2026-09-15 21:13:37 +07:00
return response.ResponseStream;
}
catch (AmazonS3Exception ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{
return Stream.Null;
}
catch (AmazonS3Exception ex)
{
2026-09-15 22:23:54 +07:00
log.LogError(ex, "MinIO download failed for {Key}", storageKey);
2026-09-15 21:13:37 +07:00
throw new StorageUnavailableException("Document download failed", ex);
}
}
2026-09-15 22:23:54 +07:00
public async Task DeleteAsync(string storageKey, CancellationToken ct)
2026-09-15 21:13:37 +07:00
{
try
{
2026-09-15 22:23:54 +07:00
await s3.DeleteObjectAsync(Bucket, storageKey, ct);
2026-09-15 21:13:37 +07:00
}
catch (AmazonS3Exception ex)
{
2026-09-15 22:23:54 +07:00
log.LogWarning(ex, "MinIO delete failed for {Key}", storageKey);
2026-09-15 21:13:37 +07:00
}
}
}