AxisStorage 2.2.0
dotnet add package AxisStorage --version 2.2.0
NuGet\Install-Package AxisStorage -Version 2.2.0
<PackageReference Include="AxisStorage" Version="2.2.0" />
<PackageVersion Include="AxisStorage" Version="2.2.0" />
<PackageReference Include="AxisStorage" />
paket add AxisStorage --version 2.2.0
#r "nuget: AxisStorage, 2.2.0"
#:package AxisStorage@2.2.0
#addin nuget:?package=AxisStorage&version=2.2.0
#tool nuget:?package=AxisStorage&version=2.2.0
AxisStorage — Documentation
An object-storage port for C# — IAxisStorage with five async operations (Upload, Download, Delete, Exists, GetPresignedUrl), every one returning AxisResult. Three optional interfaces — IAxisStorageContainer, IAxisStorageLister, IAxisStorageUrlResolver — cover container administration, prefix listing, and servable-URL resolution for adapters that support them. Three bundled adapters: AxisStorage.CloudflareR2 wires the Amazon S3 SDK against Cloudflare R2 (the same contract works for plain S3, MinIO and any other S3-compatible bucket), AxisStorage.AzureBlob wires Azure.Storage.Blobs against Azure Blob Storage — both implement every optional interface — and AxisStorage.FileSystem stores to local disk or a mounted NAS (all optional interfaces except IAxisStorageUrlResolver).
public Task<AxisResult<UploadAvatarResponse>> HandleAsync(UploadAvatarCommand cmd)
{
var key = $"avatars/{cmd.PersonId}.png";
return storage.UploadAsync(key, cmd.Content, "image/png")
.ThenAsync(() => storage.GetPresignedUrlAsync(key, TimeSpan.FromHours(1)))
.MapAsync(url => new UploadAvatarResponse { Url = url });
}
Use this page as a map: read the trunk below (~5 min) and jump straight to the detail of the group you need — without reading hundreds of lines.
The trunk (read first)
The interface in 60 seconds
public interface IAxisStorage
{
Task<AxisResult> UploadAsync(string key, Stream content, string contentType);
Task<AxisResult<Stream>> DownloadAsync(string key);
Task<AxisResult> DeleteAsync(string key);
Task<AxisResult<bool>> ExistsAsync(string key);
Task<AxisResult<string>> GetPresignedUrlAsync(string key, TimeSpan expiration);
}
Five methods. Keys are strings; vendor concepts (bucket, region, endpoint) live in the adapter's configuration. Cancellation flows in from IAxisMediatorAccessor. → The IAxisStorage contract
Why a presigned URL?
GetPresignedUrlAsync returns a time-limited URL the client can use to fetch the object directly from the bucket — no proxying through your API. Cheaper, faster, and one less stream for your server to hold open. → Presigned URLs
Bundled adapters — Cloudflare R2, Azure Blob and FileSystem
AxisStorage.CloudflareR2 is an Amazon S3 SDK adapter wired against R2's endpoint, with a typed CloudflareR2Settings (account id, access keys, bucket, optional public URL).
services.AddAxisCloudflareR2Storage(new CloudflareR2Settings
{
AccountId = "...",
AccessKey = "...",
SecretKey = "...",
BucketName = "uploads",
});
AxisStorage.AzureBlob is an Azure.Storage.Blobs adapter, with a typed AzureBlobCredentialSettings (Azure AD identity) and AzureBlobSettings (account + container).
services.AddAxisAzureBlobStorage(
new AzureBlobCredentialSettings { /* empty ⇒ ambient DefaultAzureCredential */ },
new AzureBlobSettings { AccountUrl = "https://myaccount.blob.core.windows.net", Container = "uploads" });
AxisStorage.FileSystem stores to a directory on disk (local disk, mounted NAS, mounted file server), with a typed FileSystemStorageSettings (Root).
services.AddAxisFileSystemStorage(new FileSystemStorageSettings { Root = "/var/lib/myapp/blobs" });
→ Cloudflare R2 adapter · Azure Blob adapter · FileSystem adapter
For a destination chosen at runtime (multi-tenant), each provider ships a factory — IAzureBlobStorageFactory, ICloudflareR2StorageFactory, IFileSystemStorageFactory — registered by AddAxis…StorageFactory(...).
Installation
dotnet add package AxisStorage # the abstraction
dotnet add package AxisStorage.CloudflareR2 # the Cloudflare R2 adapter (uses AWSSDK.S3)
dotnet add package AxisStorage.AzureBlob # the Azure Blob adapter (uses Azure.Storage.Blobs)
dotnet add package AxisStorage.FileSystem # the disk / NAS adapter (no extra dependency)
→ Full guide: Getting started
The map (jump to what you need)
| Group | You want to… | Detail |
|---|---|---|
Contract · IAxisStorage |
the five operations, plus the optional IAxisStorageContainer / IAxisStorageLister / IAxisStorageUrlResolver |
iaxisstorage.md |
Upload / Download · UploadAsync, DownloadAsync ⭐ |
move bytes in and out of the bucket | upload-download.md |
Presigned URLs · GetPresignedUrlAsync |
hand the client a time-limited URL | presigned-urls.md |
Cloudflare R2 · AxisStorage.CloudflareR2 |
a bundled adapter | cloudflare-r2.md |
Azure Blob · AxisStorage.AzureBlob |
another bundled adapter | azure-blob.md |
FileSystem · AxisStorage.FileSystem |
the disk / NAS adapter | filesystem.md |
| Custom adapter | write another one (plain S3, GCS) | custom-adapter.md |
| Why? | the case against direct IAmazonS3 |
why-axisstorage.md |
| Reference | every method at a glance | api-reference.md |
Start here: Getting started · The IAxisStorage contract · Why AxisStorage?
Fundamentals: Upload / Download · Presigned URLs · Cloudflare R2 adapter · Azure Blob adapter · FileSystem adapter
Reference & extras: Custom adapter · API reference
Design principles
- Vendor-neutral keys, vendor-specific config. Application code talks strings; bucket / region / endpoint live in the adapter's settings.
- Streams in, streams out. No buffer-the-whole-blob abstraction — the contract passes
Stream, so large uploads and downloads work without OOM. Existsis a typed boolean, not an exception.Ok(false)for a missing key;IsFailureonly when the call itself blew up.- Presigned URLs are first-class. Direct-to-client downloads save your egress; they are part of the contract, not a vendor escape hatch.
- The vendor SDK stays at the edge. The bundled adapters wrap
IAmazonS3andBlobServiceClientrespectively, so application code never touchesPutObjectRequestorBlobClientdirectly. - Optional capabilities are separate interfaces, not optional methods. Container administration (
IAxisStorageContainer), prefix listing (IAxisStorageLister) and servable-URL resolution (IAxisStorageUrlResolver) live outsideIAxisStorageso a provider that can't support one isn't forced to fake it —AxisStorage.FileSystem, for instance, implements the first two but not the third.
License
Apache 2.0
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- AxisResult (>= 2.2.0)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on AxisStorage:
| Package | Downloads |
|---|---|
|
AxisStorage.FileSystem
Part of the Axis Framework — an opinionated, ports-and-adapters .NET framework. |
|
|
AxisStorage.AzureBlob
Part of the Axis Framework — an opinionated, ports-and-adapters .NET framework. |
|
|
AxisStorage.CloudflareR2
Part of the Axis Framework — an opinionated, ports-and-adapters .NET framework. |
GitHub repositories
This package is not used by any popular GitHub repositories.