diff --git a/LiteCharms.Features/Extensions/S3.cs b/LiteCharms.Features/Extensions/S3.cs new file mode 100644 index 0000000..0a99a49 --- /dev/null +++ b/LiteCharms.Features/Extensions/S3.cs @@ -0,0 +1,31 @@ +using Amazon.Runtime; +using LiteCharms.Features.S3; +using LiteCharms.Features.S3.Configuration; + +namespace LiteCharms.Features.Extensions; + +public static class S3 +{ + public static IServiceCollection AddGarageS3(this IServiceCollection services, IConfiguration configuration) + { + var optionsSection = configuration.GetSection(nameof(S3Settings)); + services.Configure(optionsSection); + + var options = optionsSection.Get() + ?? throw new InvalidOperationException("S3 configuration section is missing."); + + var credentials = new BasicAWSCredentials(options.AccessKey, options.SecretKey); + + var s3Config = new AmazonS3Config + { + ServiceURL = options.ServiceUrl, + AuthenticationRegion = options.Region, + ForcePathStyle = true, + }; + + services.AddSingleton(new AmazonS3Client(credentials, s3Config)); + services.AddScoped(); + + return services; + } +} diff --git a/LiteCharms.Features/LiteCharms.Features.csproj b/LiteCharms.Features/LiteCharms.Features.csproj index a9aedad..1e65e11 100644 --- a/LiteCharms.Features/LiteCharms.Features.csproj +++ b/LiteCharms.Features/LiteCharms.Features.csproj @@ -128,6 +128,16 @@ + + + + + + + + + + diff --git a/LiteCharms.Features/S3/Configuration/S3Settings.cs b/LiteCharms.Features/S3/Configuration/S3Settings.cs new file mode 100644 index 0000000..dfcb0c0 --- /dev/null +++ b/LiteCharms.Features/S3/Configuration/S3Settings.cs @@ -0,0 +1,14 @@ +namespace LiteCharms.Features.S3.Configuration; + +public class S3Settings +{ + public string? ServiceUrl { get; set; } + + public string? AccessKey { get; set; } + + public string? SecretKey { get; set; } + + public string? BucketName { get; set; } + + public string? Region { get; set; } +} diff --git a/LiteCharms.Features/S3/S3Service.cs b/LiteCharms.Features/S3/S3Service.cs new file mode 100644 index 0000000..b55c267 --- /dev/null +++ b/LiteCharms.Features/S3/S3Service.cs @@ -0,0 +1,28 @@ +namespace LiteCharms.Features.S3; + +public class S3Service(IAmazonS3 amazonS3) +{ + public async Task> UploadFileAsync(string bucketName, string fileName, Stream fileStream, string contentType, string cdnBaseUrl, CancellationToken cancellationToken = default) + { + try + { + var putRequest = new PutObjectRequest + { + BucketName = bucketName, + Key = fileName, + InputStream = fileStream, + ContentType = contentType + }; + + var response = await amazonS3.PutObjectAsync(putRequest, cancellationToken); + + return response.HttpStatusCode != System.Net.HttpStatusCode.OK + ? Result.Fail($"Failed to upload {fileName} to S3.") + : Result.Ok(string.Format(cdnBaseUrl, bucketName, fileName)); + } + catch (Exception ex) + { + return Result.Fail(new Error($"Error uploading {fileName} to S3: {ex.Message}").CausedBy(ex)); + } + } +}