The IStorageService abstracts file operations, allowing you to switch between local file system storage and cloud providers (like S3 or Azure Blobs) without changing your business logic.
Specify the root path where files should be stored.
"Storage": {
"FileSystem": {
"RootPath": "/app/storage"
}
}
public class UploadProfilePhotoHandler(IStorageService storage, IProfileRepository repository)
: ICommandHandler<UploadPhotoCommand, Result<Guid>>
{
public async Task<Result<Guid>> HandleAsync(UploadPhotoCommand cmd, CancellationToken ct)
{
// 1. Upload the file
var fileName = $"{Guid.NewGuid()}{Path.GetExtension(cmd.FileName)}";
var uploadResult = await storage.UploadAsync(cmd.FileStream, "profiles", fileName, ct);
if (!uploadResult.IsSuccess) return uploadResult;
// 2. Get the permanent URL or path
var fileUrl = await storage.GetUrlAsync(uploadResult.Data.Path, ct);
// ... update database with the path
return ResultFactory.OnSuccess(uploadResult.Data.Id);
}
}
UploadAsync: Stores a stream and returns a unique identifier/path.DownloadAsync: Retrieves a file as a stream.DeleteAsync: Removes a file.GetUrlAsync: Returns a URL for accessing the file (can be a local path or a pre-signed S3 URL).By coding against IStorageService, your application doesn’t care if the file is on a local disk or in a distributed blob store. This is ideal for containerized deployments.