Table of Contents

Class S3ObjectStorage

Namespace
Builvero.Infrastructure.Services
Assembly
Builvero.Infrastructure.dll

S3 implementation of IObjectStorage. Handles actual AWS S3 operations with support for LocalStack/minio via Endpoint and ForcePathStyle.

public sealed class S3ObjectStorage : IObjectStorage
Inheritance
S3ObjectStorage
Implements
Inherited Members

Constructors

S3ObjectStorage(IAmazonS3, IOptions<S3Options>, ILogger<S3ObjectStorage>)

Initializes a new instance of the S3ObjectStorage class.

public S3ObjectStorage(IAmazonS3 s3Client, IOptions<S3Options> s3Options, ILogger<S3ObjectStorage> logger)

Parameters

s3Client IAmazonS3

The AWS S3 client for performing S3 operations.

s3Options IOptions<S3Options>

S3 configuration options including bucket name, region, endpoint, and path style settings.

logger ILogger<S3ObjectStorage>

Logger for recording S3 operations and errors.

Exceptions

InvalidOperationException

Thrown when S3 is enabled but ProfilePhotosBucket is not configured.

Methods

DeleteAsync(string, CancellationToken)

Deletes a file from S3.

public Task<bool> DeleteAsync(string objectKey, CancellationToken cancellationToken = default)

Parameters

objectKey string

Storage object key of the file to delete.

cancellationToken CancellationToken

Cancellation token to cancel the operation.

Returns

Task<bool>

true if the file was successfully deleted; false if the object key is null or whitespace.

Remarks

If the object key is null or whitespace, the method returns false without making an S3 API call.

Note: S3 delete operations are idempotent. Deleting a non-existent object does not throw an error.

Exceptions

Exception

Thrown when S3 API returns an error during deletion.

GenerateGetUrlAsync(string, TimeSpan?, CancellationToken)

Generates a GET URL for retrieving a file from S3, either as a public URL or presigned URL based on configuration.

public Task<string> GenerateGetUrlAsync(string objectKey, TimeSpan? expiresIn = null, CancellationToken cancellationToken = default)

Parameters

objectKey string

Storage object key (e.g., "profile-photos/{userId}/{uuid}.jpg").

expiresIn TimeSpan?

Time until the URL expires (only used for presigned URLs). Defaults to 15 minutes if not specified.

cancellationToken CancellationToken

Cancellation token to cancel the operation.

Returns

Task<string>

A public URL if UsePublicUrls is true; otherwise, a presigned GET URL. Returns an empty string if the object key is null or whitespace.

Remarks

This method respects the UsePublicUrls configuration setting:

  • If UsePublicUrls is true, returns a plain public URL (for backward compatibility with public buckets)
  • If UsePublicUrls is false, generates a presigned URL for secure access to private buckets

For guaranteed presigned URLs regardless of configuration, use GeneratePresignedGetUrlAsync(string, TimeSpan?, CancellationToken) instead.

GeneratePresignedGetUrlAsync(string, TimeSpan?, CancellationToken)

Generates a presigned GET URL. This method ALWAYS returns a presigned URL, regardless of the UsePublicUrls setting. Use this when you need guaranteed presigning.

public Task<string> GeneratePresignedGetUrlAsync(string objectKey, TimeSpan? expiresIn = null, CancellationToken cancellationToken = default)

Parameters

objectKey string

Storage object key

expiresIn TimeSpan?

Time until the URL expires

cancellationToken CancellationToken

Cancellation token

Returns

Task<string>

Presigned GET URL with X-Amz- query parameters

GeneratePublicGetUrl(string)

Generates a plain public S3 URL (for truly public buckets). This method constructs a URL without presigning and should only be used for public buckets.

public string GeneratePublicGetUrl(string objectKey)

Parameters

objectKey string

Storage object key

Returns

string

Plain public S3 URL

GenerateUploadUrlAsync(string, string, TimeSpan?, CancellationToken)

Generates a presigned URL for uploading a file to S3.

public Task<(string UploadUrl, string ObjectKey)> GenerateUploadUrlAsync(string objectKey, string contentType, TimeSpan? expiresIn = null, CancellationToken cancellationToken = default)

Parameters

objectKey string

Storage object key (e.g., "profile-photos/{userId}/{uuid}.jpg").

contentType string

MIME type of the file (e.g., "image/jpeg", "application/pdf").

expiresIn TimeSpan?

Time until the URL expires. Defaults to 5 minutes if not specified.

cancellationToken CancellationToken

Cancellation token to cancel the operation.

Returns

Task<(string UploadUrl, string ObjectKey)>

A tuple containing the presigned upload URL and the object key.

Remarks

The presigned URL allows clients to upload files directly to S3 without exposing AWS credentials. The URL includes:

  • Bucket name and object key
  • HTTP verb (PUT)
  • Content type constraint
  • Expiration timestamp
  • Signature for authentication

The content type is enforced by the presigned URL, ensuring clients upload files with the correct MIME type.

Exceptions

Exception

Thrown when S3 API returns an error during URL generation.

UploadAsync(string, Stream, string, CancellationToken)

Uploads a file stream to S3.

public Task<string> UploadAsync(string objectKey, Stream fileStream, string contentType, CancellationToken cancellationToken = default)

Parameters

objectKey string

Storage object key where the file will be stored (e.g., "profile-photos/{userId}/{uuid}.jpg").

fileStream Stream

The file stream to upload. The stream will be read from its current position.

contentType string

MIME type of the file (e.g., "image/jpeg", "application/pdf").

cancellationToken CancellationToken

Cancellation token to cancel the operation.

Returns

Task<string>

The object key where the file was stored (same as the input objectKey).

Remarks

The file is uploaded with server-side encryption using AES256. The content type is set on the S3 object for proper MIME type handling when the file is retrieved.

The stream is read from its current position. Ensure the stream is positioned at the start of the file data before calling this method.

Exceptions

Exception

Thrown when S3 API returns an error during upload.