using Amazon.S3;
using Amazon.S3.Model;
using Infrastructure.Configuration;
using Microsoft.Extensions.Configuration;
namespace Infrastructure.FileUpload;
///
/// File storage service backed by an S3-compatible object store (e.g. SeaweedFS, AWS S3).
/// Configured via application configuration (backed by environment variables).
///
public class S3FileStorageProvider : IFileStorageProvider, IDisposable
{
private readonly string _bucket;
private readonly IAmazonS3 _client;
///
/// Initializes a new instance of the class, reading storage
/// configuration (SEAWEEDFS_SERVICE_URL, SEAWEEDFS_ACCESS_KEY_ID,
/// SEAWEEDFS_SECRET_ACCESS_KEY, SEAWEEDFS_BUCKET) from .
///
///
/// Thrown when any of the required configuration values is not set.
///
public S3FileStorageProvider(IConfiguration configuration)
{
string serviceUrl = ConfigurationHelpers.GetKeyOrThrow(
configuration,
ConfigurationKeys.SeaweedFsServiceUrl
);
string accessKeyId = ConfigurationHelpers.GetKeyOrThrow(
configuration,
ConfigurationKeys.SeaweedFsAccessKeyId
);
string secretAccessKey = ConfigurationHelpers.GetKeyOrThrow(
configuration,
ConfigurationKeys.SeaweedFsSecretAccessKey
);
_bucket = ConfigurationHelpers.GetKeyOrThrow(
configuration,
ConfigurationKeys.SeaweedFsBucket
);
AmazonS3Config config = new() { ServiceURL = serviceUrl, ForcePathStyle = true };
_client = new AmazonS3Client(accessKeyId, secretAccessKey, config);
}
///
public async Task UploadAsync(
string key,
Stream content,
string contentType,
CancellationToken cancellationToken = default
)
{
PutObjectRequest request = new()
{
BucketName = _bucket,
Key = key,
InputStream = content,
ContentType = contentType,
};
await _client.PutObjectAsync(request, cancellationToken);
}
///
public async Task DeleteAsync(string key, CancellationToken cancellationToken = default)
{
DeleteObjectRequest request = new() { BucketName = _bucket, Key = key };
await _client.DeleteObjectAsync(request, cancellationToken);
}
///
public string GetPresignedUrl(string key, TimeSpan expiresIn)
{
GetPreSignedUrlRequest request = new()
{
BucketName = _bucket,
Key = key,
Expires = DateTime.UtcNow.Add(expiresIn),
};
return _client.GetPreSignedURL(request);
}
///
public void Dispose()
{
_client.Dispose();
GC.SuppressFinalize(this);
}
}