@@ -1,12 +0,0 @@
|
||||
|
||||
using Pldpro.Web.Services.Models;
|
||||
|
||||
namespace Pldpro.Web.Services;
|
||||
|
||||
public interface IStorageService
|
||||
{
|
||||
Task<IEnumerable<BucketItem>> ListBucketsAsync(CancellationToken ct = default);
|
||||
Task CreateBucketAsync(string bucketName, CancellationToken ct = default);
|
||||
Task<IEnumerable<ObjectItem>> ListObjectsAsync(string bucket, CancellationToken ct = default);
|
||||
Task UploadObjectAsync(string bucket, string key, Stream content, string contentType, CancellationToken ct = default);
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
namespace Pldpro.Web.Services.Models;
|
||||
|
||||
public sealed record BucketItem(string Name, DateTime? CreationDate);
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
namespace Pldpro.Web.Services.Models;
|
||||
|
||||
public sealed record ObjectItem(string Key, long? Size, DateTime? LastModified);
|
||||
@@ -1,7 +0,0 @@
|
||||
|
||||
namespace Pldpro.Web.Models;
|
||||
|
||||
public sealed class S3CreateBucketDto
|
||||
{
|
||||
public string BucketName { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
|
||||
using Amazon.S3;
|
||||
using Amazon.S3.Model;
|
||||
using Pldpro.Web.Services.Models;
|
||||
|
||||
namespace Pldpro.Web.Services;
|
||||
|
||||
public sealed class S3StorageService(IAmazonS3 s3) : IStorageService
|
||||
{
|
||||
private readonly IAmazonS3 _s3 = s3;
|
||||
|
||||
public async Task<IEnumerable<BucketItem>> ListBucketsAsync(CancellationToken ct = default)
|
||||
{
|
||||
var resp = await _s3.ListBucketsAsync(ct);
|
||||
return resp.Buckets.Select(b => new BucketItem(b.BucketName, b.CreationDate));
|
||||
}
|
||||
|
||||
public async Task CreateBucketAsync(string bucketName, CancellationToken ct = default)
|
||||
{
|
||||
// Für S3-kompatible Endpoints reicht häufig nur der Name
|
||||
var req = new PutBucketRequest { BucketName = bucketName };
|
||||
await _s3.PutBucketAsync(req, ct);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ObjectItem>> ListObjectsAsync(string bucket, CancellationToken ct = default)
|
||||
{
|
||||
var items = new List<ObjectItem>();
|
||||
string? token = null;
|
||||
do
|
||||
{
|
||||
var resp = await _s3.ListObjectsV2Async(new ListObjectsV2Request
|
||||
{
|
||||
BucketName = bucket,
|
||||
ContinuationToken = token
|
||||
}, ct);
|
||||
|
||||
items.AddRange(resp.S3Objects.Select(o => new ObjectItem(o.Key, o.Size, o.LastModified)));
|
||||
token = resp.IsTruncated ? resp.NextContinuationToken : null;
|
||||
} while (token is not null);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
public async Task UploadObjectAsync(string bucket, string key, Stream content, string contentType, CancellationToken ct = default)
|
||||
{
|
||||
var req = new PutObjectRequest
|
||||
{
|
||||
BucketName = bucket,
|
||||
Key = key,
|
||||
InputStream = content,
|
||||
ContentType = contentType
|
||||
};
|
||||
await _s3.PutObjectAsync(req, ct);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user