This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
namespace LiteCharms.Features.S3.Abstractions;
|
||||
|
||||
public interface IS3Service
|
||||
{
|
||||
Task<Result<string>> UploadFileAsync(string fileName, Stream fileStream, string contentType, CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace LiteCharms.Features.S3.Abstractions;
|
||||
|
||||
public abstract class S3ServiceBase(IAmazonS3 amazonS3)
|
||||
{
|
||||
protected readonly IAmazonS3 client = amazonS3;
|
||||
|
||||
public abstract Task<Result<string>> UploadFileAsync(string fileName, Stream fileStream, string contentType, CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using LiteCharms.Features.S3.Abstractions;
|
||||
|
||||
namespace LiteCharms.Features.S3;
|
||||
|
||||
public class BookstoreInvoicesS3Service(IConfiguration configuration, [FromKeyedServices(Constants.BookshopInvoicesBucketName)] IAmazonS3 amazonS3) :
|
||||
S3ServiceBase(amazonS3), IS3Service
|
||||
{
|
||||
public override async Task<Result<string>> UploadFileAsync(string fileName, Stream fileStream, string contentType, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var bucketName = configuration.GetSection($"{Constants.BookshopInvoicesS3SettingsSection}:BucketName").Value!;
|
||||
var cdnBaseUrl = configuration.GetSection($"{Constants.BookshopInvoicesS3SettingsSection}:CdnBaseUrl").Value!;
|
||||
|
||||
if(string.IsNullOrWhiteSpace(bucketName))
|
||||
return Result.Fail<string>("Bucket name is not configured.");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(cdnBaseUrl))
|
||||
return Result.Fail<string>("CDN base URL is not configured.");
|
||||
|
||||
var response = await client.PutObjectAsync(new PutObjectRequest
|
||||
{
|
||||
BucketName = bucketName,
|
||||
Key = fileName,
|
||||
InputStream = fileStream,
|
||||
ContentType = contentType
|
||||
}, 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using LiteCharms.Features.S3.Abstractions;
|
||||
|
||||
namespace LiteCharms.Features.S3;
|
||||
|
||||
public class BookstoreQuotesS3Service(IConfiguration configuration, [FromKeyedServices(Constants.BookshopQuotesBucketName)] IAmazonS3 amazonS3) :
|
||||
S3ServiceBase(amazonS3), IS3Service
|
||||
{
|
||||
public override async Task<Result<string>> UploadFileAsync(string fileName, Stream fileStream, string contentType, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var bucketName = configuration.GetSection($"{Constants.BookshopQuotesS3SettingsSection}:BucketName").Value!;
|
||||
var cdnBaseUrl = configuration.GetSection($"{Constants.BookshopQuotesS3SettingsSection}:CdnBaseUrl").Value!;
|
||||
|
||||
if(string.IsNullOrWhiteSpace(bucketName))
|
||||
return Result.Fail<string>("Bucket name is not configured.");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(cdnBaseUrl))
|
||||
return Result.Fail<string>("CDN base URL is not configured.");
|
||||
|
||||
var response = await client.PutObjectAsync(new PutObjectRequest
|
||||
{
|
||||
BucketName = bucketName,
|
||||
Key = fileName,
|
||||
InputStream = fileStream,
|
||||
ContentType = contentType
|
||||
}, 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using LiteCharms.Features.S3.Abstractions;
|
||||
|
||||
namespace LiteCharms.Features.S3;
|
||||
|
||||
public class BookstoreS3Service(IConfiguration configuration, [FromKeyedServices(Constants.BookshopBucketName)] IAmazonS3 amazonS3) :
|
||||
S3ServiceBase(amazonS3), IS3Service
|
||||
{
|
||||
public override async Task<Result<string>> UploadFileAsync(string fileName, Stream fileStream, string contentType, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var bucketName = configuration.GetSection($"{Constants.BookshopS3SettingsSection}:BucketName").Value!;
|
||||
var cdnBaseUrl = configuration.GetSection($"{Constants.BookshopS3SettingsSection}:CdnBaseUrl").Value!;
|
||||
|
||||
if(string.IsNullOrWhiteSpace(bucketName))
|
||||
return Result.Fail<string>("Bucket name is not configured.");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(cdnBaseUrl))
|
||||
return Result.Fail<string>("CDN base URL is not configured.");
|
||||
|
||||
var response = await client.PutObjectAsync(new PutObjectRequest
|
||||
{
|
||||
BucketName = bucketName,
|
||||
Key = fileName,
|
||||
InputStream = fileStream,
|
||||
ContentType = contentType
|
||||
}, 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,4 +11,6 @@ public class S3Settings
|
||||
public string? BucketName { get; set; }
|
||||
|
||||
public string? Region { get; set; }
|
||||
|
||||
public string? CdnBaseUrl { get; set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace LiteCharms.Features.S3;
|
||||
|
||||
public static class Constants
|
||||
{
|
||||
public const string BookshopS3SettingsSection = "BookshopS3Settings";
|
||||
public const string BookshopInvoicesS3SettingsSection = "BookshopInvoicesS3Settings";
|
||||
public const string BookshopQuotesS3SettingsSection = "BookshopQuotesS3Settings";
|
||||
|
||||
public const string BookshopBucketName = "bookshop";
|
||||
public const string BookshopInvoicesBucketName = "bookshop.invoices";
|
||||
public const string BookshopQuotesBucketName = "bookshop.quotes";
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
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