@@ -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<S3Settings>(optionsSection);
|
||||
|
||||
var options = optionsSection.Get<S3Settings>()
|
||||
?? 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<IAmazonS3>(new AmazonS3Client(credentials, s3Config));
|
||||
services.AddScoped<S3Service>();
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -128,6 +128,16 @@
|
||||
<Using Include="FluentResults" />
|
||||
<Using Include="Mediator" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Amazon S3 SDK -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AWSSDK.Extensions.NetCore.Setup" Version="4.0.3.40" />
|
||||
<PackageReference Include="AWSSDK.S3" Version="4.0.23.3" />
|
||||
|
||||
<!-- global Usings -->
|
||||
<Using Include="Amazon.S3" />
|
||||
<Using Include="Amazon.S3.Model" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Shared Usings -->
|
||||
<ItemGroup>
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace LiteCharms.Features.S3;
|
||||
|
||||
public class S3Service(IAmazonS3 amazonS3)
|
||||
{
|
||||
public async Task<Result<string>> 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<string>($"Failed to upload {fileName} to S3.")
|
||||
: Result.Ok(string.Format(cdnBaseUrl, bucketName, fileName));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result.Fail<string>(new Error($"Error uploading {fileName} to S3: {ex.Message}").CausedBy(ex));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user