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); } }