Cloud Agnostic - Storing & serving files

Cloud agnostic series
  1. Depending on a colour
  2. Depending on a colour Pt. 2 - Needs, Possibilities and Limitations
  3. Cloud Agnostic - introducing the AheadDockerized .NET Solution
  4. Cloud Agnostic - Storing & serving files

Let us start with a relatively simple, ubiquitous but necessary service: Storage of files. In ahead these are needed for attachments, images, videos and the like.

After investigating a bit, it appears that the safest bet here is to use something that is Amazon S3-compatible. AWS, by being first here, essentially set the standard for cloud storage, and many companies will offer such “S3-compatible” storage for you to use. Here’s an example from Switzerland.

Granted, using Azure Blob Storage is straightforward from a developer perspective: Having a local “emulator” is as easy as saying npm install azurite. I could imagine that there might be a similar offering for S3-compatible storage, but considering that I have an Aspire-project available, setting up a container is also a straightforward activity. The company min.io offers an “object store” that can be run at hyperscale as well as locally on a Docker container. The relevant code is hosted at github

Defining such a container as a resource in Aspire looks like this:

Gist not showing up? Most likely you're using Chrome. Reload the page to see the gist.

People who know docker containers probably recognize the different settings that are being set:

Aspire gives you a fluent API to define settings on the different kind of resources. Interesting are also the two variables minioUser, minioPassword which are defined further up:

During development, these values come from a “Parameters” section in appSettings.Development.json. Once I start the solution by running the AppHost Aspire project, I can access the min.io dashboard by clicking the provided link in the Aspire dashboard:

Aspire Dashboard showing the known resources

Aspire Dashboard showing the known resources

In the dashboard I can log in with the provided user / password values and create an access key:

min.io console that allows to create access keys

min.io console that allows to create access keys

These will be required when accessing the service.

The relevant Nuget to access the service is simply called minio, and provides an up-to-date library to talk to min.io (and by extension S3 compatible) services.

The Ahead.Dockerized solution introduces a blob storage interface with some example API that is linked to UI in order to be able to use it:

⬇️ This is the implementation of the upload – it takes an IFormFile instance and stores it in the service. I found it amusing that, just coming from an Aspire frontend, I ended up using a fluent interface again. While they’re kind of nice to read, getting there is not always as obvious as one cannot see from the API what is mandatory vs what is not, hence it is sometimes something of a trial and error to get the right incantation.

Another thing I wanted to check out is the signed url functionality - Links to files in ahead are usually written like api/files/{fileId} - the server then redirects to a signed url, which lets you see the file for a limited amount of time:

This is how to get the necessary url through the min.io API:

In this case, the link expires after one hour.

All in all, blob storage is, as expected, one of the easier things to treat in a cloud-agnostic way.