83 lines
2.5 KiB
C#
83 lines
2.5 KiB
C#
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;
|
|
|
|
public static string FileNameNow(string name)
|
|
{
|
|
return $"{Slug(name)}_{DateTime.UtcNow:yyyyMMddHHmmss}";
|
|
}
|
|
|
|
private static string Slug(string name)
|
|
{
|
|
var slug = new string(name.Trim().ToLowerInvariant()
|
|
.Select(c => char.IsLetterOrDigit(c) ? c : '-')
|
|
.ToArray()).Trim('-');
|
|
return slug.Length == 0 ? "document" : slug;
|
|
}
|
|
|
|
public async Task<string> UploadAsync(string projectName, string fileName, string contentType, Stream body, CancellationToken ct)
|
|
{
|
|
var key = $"{Slug(projectName)}/{FileNameNow(fileName)}.html";
|
|
try
|
|
{
|
|
await s3.PutObjectAsync(new PutObjectRequest
|
|
{
|
|
BucketName = Bucket,
|
|
Key = key,
|
|
InputStream = body,
|
|
ContentType = contentType,
|
|
AutoCloseStream = false,
|
|
}, ct);
|
|
return key;
|
|
}
|
|
catch (AmazonS3Exception ex)
|
|
{
|
|
log.LogError(ex, "MinIO upload failed for {Key}", key);
|
|
throw new StorageUnavailableException("Document upload failed", ex);
|
|
}
|
|
}
|
|
|
|
public async Task<Stream> DownloadAsync(string storageKey, CancellationToken ct)
|
|
{
|
|
try
|
|
{
|
|
var response = await s3.GetObjectAsync(Bucket, storageKey, ct);
|
|
return response.ResponseStream;
|
|
}
|
|
catch (AmazonS3Exception ex) when (ex.StatusCode == HttpStatusCode.NotFound)
|
|
{
|
|
return Stream.Null;
|
|
}
|
|
catch (AmazonS3Exception ex)
|
|
{
|
|
log.LogError(ex, "MinIO download failed for {Key}", storageKey);
|
|
throw new StorageUnavailableException("Document download failed", ex);
|
|
}
|
|
}
|
|
|
|
public async Task DeleteAsync(string storageKey, CancellationToken ct)
|
|
{
|
|
try
|
|
{
|
|
await s3.DeleteObjectAsync(Bucket, storageKey, ct);
|
|
}
|
|
catch (AmazonS3Exception ex)
|
|
{
|
|
log.LogWarning(ex, "MinIO delete failed for {Key}", storageKey);
|
|
}
|
|
}
|
|
}
|