ccf30ac36b
continuous-integration/drone/pr Build is passing
Implemented and tested DeleteFileAsync()
84 lines
2.9 KiB
C#
84 lines
2.9 KiB
C#
using static LiteCharms.Features.Extensions.Hash;
|
|
|
|
namespace LiteCharms.Features.S3.Abstractions;
|
|
|
|
public abstract class S3ServiceBase(IAmazonS3 amazonS3)
|
|
{
|
|
protected readonly IAmazonS3 Client = amazonS3;
|
|
|
|
protected abstract string BucketName { get; }
|
|
protected abstract string CdnBaseUrl { get; }
|
|
|
|
public virtual async Task<Result<string>> UploadFileAsync(string fileName, Stream fileStream, string contentType, CancellationToken cancellationToken = default)
|
|
{
|
|
try
|
|
{
|
|
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.");
|
|
|
|
using var stream = new MemoryStream();
|
|
|
|
await fileStream.CopyToAsync(stream, cancellationToken);
|
|
await fileStream.DisposeAsync();
|
|
|
|
stream.Seek(0, SeekOrigin.Begin);
|
|
|
|
var fileHash = StreamToSha256Hash(stream);
|
|
|
|
if(string.IsNullOrWhiteSpace(fileHash))
|
|
return Result.Fail<string>("Failed to compute file hash.");
|
|
|
|
var fileKey = $"{fileHash.ToLower()}{Path.GetExtension(fileName)}";
|
|
|
|
var putRequest = new PutObjectRequest
|
|
{
|
|
BucketName = BucketName,
|
|
Key = fileKey,
|
|
InputStream = stream,
|
|
ContentType = contentType,
|
|
UseChunkEncoding = false
|
|
};
|
|
|
|
stream.Seek(0, SeekOrigin.Begin);
|
|
|
|
var response = await Client.PutObjectAsync(putRequest, cancellationToken);
|
|
|
|
return response.HttpStatusCode != System.Net.HttpStatusCode.OK
|
|
? Result.Fail<string>($"Failed to upload {fileName} to S3.")
|
|
: Result.Ok($"{CdnBaseUrl}/{fileKey}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return Result.Fail<string>(new Error($"Error uploading {fileName} to S3: {ex.Message}").CausedBy(ex));
|
|
}
|
|
}
|
|
|
|
public virtual async Task<Result> DeleteFileAsync(string fileKey, CancellationToken cancellationToken = default)
|
|
{
|
|
try
|
|
{
|
|
if (string.IsNullOrWhiteSpace(BucketName))
|
|
return Result.Fail("Bucket name is not configured.");
|
|
|
|
var deleteRequest = new DeleteObjectRequest
|
|
{
|
|
BucketName = BucketName,
|
|
Key = fileKey
|
|
};
|
|
|
|
var response = await Client.DeleteObjectAsync(deleteRequest, cancellationToken);
|
|
|
|
return response.HttpStatusCode != System.Net.HttpStatusCode.NoContent
|
|
? Result.Fail($"Failed to delete {fileKey} from S3.")
|
|
: Result.Ok();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return Result.Fail(new Error($"Error deleting {fileKey} from S3: {ex.Message}").CausedBy(ex));
|
|
}
|
|
}
|
|
}
|