Using FluentStorage for polycloud file storage in C#
Posted: (EET/GMT+2)
If your C# application needs to store files in more than one place (read: cloud), it can be useful to hide the storage provider behind a small abstraction. I have been investigating FluentStorage lately. It is a C# library for polycloud file storage. The idea is simple: use one common API for different storage providers such as Azure Blob Storage, AWS S3, Google Cloud Storage, FTP, and local disk.
This can be very useful when the application logic should not care too much about where the file actually lives. For example, the same application might use local disk during development and Azure Blob Storage in production.
Start with the main package:
dotnet add package FluentStorage
Then add the provider package you need. For Azure Blob Storage:
dotnet add package FluentStorage.Azure.Blobs
FluentStorage uses the IStore abstraction for storage operations. Let's see a code example:
using FluentStorage; using FluentStorage.Azure.Blobs; StorageFactory.Modules.UseAzureBlobStorage(); IStore store = StorageFactory.FromConnectionString( azure.blob://account=account_name;key=secret_value");
For Azure Blob Storage, the first part of the object path is the container name:
mycontainer/reports/report.txt
This means the object reports/report.txt is stored in the container mycontainer.
Writing a small text file could look something like this:
using System.Text;
byte[] data = Encoding.UTF8.GetBytes("Hello from FluentStorage!");
await store.SetBytes("mycontainer/reports/hello.txt", data);
And reading it back:
byte[] downloaded = await store.GetBytes("mycontainer/reports/hello.txt");
string text = Encoding.UTF8.GetString(downloaded);
Console.WriteLine(text);
You can also check whether an object exists:
bool exists = await store.ObjectExists("mycontainer/reports/hello.txt");
Console.WriteLine(exists);
The benefit is not that this is shorter than the native Azure SDK in every case. The benefit is that the application can be written against a storage concept instead of a specific cloud vendor.
That can make sense when you need to support more than one storage provider, or you want to test storage logic locally. Still, do not hide everything. Storage providers are not identical.
For example, metadata, versioning, access tiers, presigned URLs, permissions, and directory behavior can differ between providers. A common abstraction is useful, but the real storage system still matters.
Given this, I like to keep FluentStorage behind my own little interface abstraction. This gives me one more stable layer if you later change storage library, provider, or package version.
public interface MyFileStorage
{
Task SaveText(string path, string content,
CancellationToken cancellationToken);
Task<string?> ReadText(string path,
CancellationToken cancellationToken);
}
A simple implementation can wrap the FluentStorage:
using System.Text;
using FluentStorage;
public sealed class FluentAppFileStorage(IStore store) : MyFileStorage
{
public async Task SaveText(string path,
string content, CancellationToken cancellationToken)
{
byte[] data = Encoding.UTF8.GetBytes(content);
await store.SetBytes(path, data, cancellationToken);
}
public async Task<string?> ReadText(string path,
CancellationToken cancellationToken)
{
if (!await store.ObjectExists(path, cancellationToken))
{
return null;
}
byte[] data = await store.GetBytes(path, cancellationToken);
return Encoding.UTF8.GetString(data);
}
}
Then the rest of the application can depend on AppFileStorage instead of knowing
about Azure Blob Storage, S3, SFTP, or local disk directly.
Good things to decide before using any storage abstraction:
- which provider features does the application really need?
- what should object paths look like?
- where are credentials stored?
- how are large files streamed?
- who owns retry and error handling?
- do you need direct access to the native provider SDK?
For simple applications that only ever use Azure Blob Storage, the official Azure SDK may be the clearest choice. But for applications that need a common storage API across providers, FluentStorage is worth knowing about.
The NuGet package is named simply FluentStorage (see here).