Skip to main content

Packages Reference

Vali-Blob is distributed as a family of 12 focused NuGet packages. Install only what your project needs. All packages target net8.0 and net9.0 and are versioned together — always use the same version across all Vali-Blob packages in a project.


Summary Table

PackageRequiredCloud DependencySupports ResumableSupports Presigned URLs
Vali-Blob.CoreAlwaysNone
Vali-Blob.AWSWhen using S3AWSSDK.S3YesYes
Vali-Blob.AzureWhen using AzureAzure.Storage.BlobsYesYes (SAS tokens)
Vali-Blob.GCPWhen using GCPGoogle.Cloud.Storage.V1YesYes (V4 signed URLs)
Vali-Blob.OCIWhen using OCIOracle SDKYesYes (PARs via API)
Vali-Blob.SupabaseWhen using Supabasesupabase-csharpNoYes
Vali-Blob.LocalFor local/devNoneYesYes (HTTP)
Vali-Blob.RedisFor Redis sessionsStackExchange.RedisSession Store
Vali-Blob.EFCoreFor DB sessionsEF CoreSession Store
Vali-Blob.TestingIn test projectsNoneYesYes
Vali-Blob.HealthChecksFor health endpointsASP.NET Core
Vali-Blob.ImageSharpFor image processingSixLabors.ImageSharp

Vali-Blob.Core

The foundation package. Every Vali-Blob project requires this package.

dotnet add package Vali-Blob.Core

What it provides:

  • IStorageProvider — the core storage interface with 11 operations
  • IStorageFactory — resolves named providers by key
  • BaseStorageProvider — base class with pipeline execution, resilience hooks, and telemetry
  • StorageResult<T> / StorageResult — explicit result/error pattern, no exceptions for expected failures
  • StoragePath — safe path building with date/hash/random suffixes and sanitization
  • StorageErrorCode — enum of all well-known error conditions
  • StoragePipelineBuilder — fluent middleware registration
  • DI extension methods: AddVali-Blob(), AddProvider<T>(), WithPipeline()
  • IResumableUploadProvider — optional interface for resumable upload support
  • IPresignedUrlProvider — optional interface for presigned URL generation
  • All request/response types: UploadRequest, DownloadRequest, FileMetadata, FileEntry, UploadResult
  • Event system: IStorageEventHandler<T>, StorageEventContext

Key dependencies:

DependencyPurpose
Microsoft.Extensions.DependencyInjection.AbstractionsDI integration
Microsoft.Extensions.OptionsOptions pattern
Microsoft.Extensions.Logging.AbstractionsStructured logging
PropertyValue
Target frameworksnet8.0; net9.0
RequiredYes — always install this
External cloud dependencyNone

Vali-Blob.AWS

Amazon S3 provider implementation.

dotnet add package Vali-Blob.Core
dotnet add package Vali-Blob.AWS

What it provides:

  • AWSS3Provider — full IStorageProvider + IResumableUploadProvider + IPresignedUrlProvider implementation
  • AWSS3Options — provider configuration:
builder.Services
.AddVali-Blob(o => o.DefaultProvider = "aws")
.AddProvider<AWSS3Provider>("aws", opts =>
{
opts.BucketName = "my-bucket";
opts.Region = "us-east-1";
opts.AccessKey = config["AWS:AccessKey"]!;
opts.SecretKey = config["AWS:SecretKey"]!;
opts.ServiceUrl = null; // set to "http://localhost:4566" for LocalStack
});

AWSS3Options fields:

FieldTypeDescription
BucketNamestringS3 bucket name
RegionstringAWS region code (e.g., us-east-1)
AccessKeystring?AWS access key (leave null to use IAM role)
SecretKeystring?AWS secret key (leave null to use IAM role)
ServiceUrlstring?Override endpoint URL (for LocalStack, MinIO, etc.)
ForcePathStyleboolUse path-style URLs instead of virtual-hosted; required for LocalStack

Key dependency: AWSSDK.S3

IAM Roles

In production on AWS (EC2, ECS, Lambda), do not set AccessKey and SecretKey. Leave them null and grant the instance/task IAM role the necessary S3 permissions. This is more secure and eliminates credential rotation.

PropertyValue
Target frameworksnet8.0; net9.0
Supports resumable uploadsYes (S3 multipart upload)
Supports presigned URLsYes

Vali-Blob.Azure

Azure Blob Storage provider implementation.

dotnet add package Vali-Blob.Core
dotnet add package Vali-Blob.Azure

What it provides:

  • AzureBlobProvider — full IStorageProvider + IResumableUploadProvider + IPresignedUrlProvider
  • AzureBlobOptions:
.AddProvider<AzureBlobProvider>("azure", opts =>
{
opts.ConnectionString = config["Azure:ConnectionString"]!;
opts.ContainerName = "my-container";
})

AzureBlobOptions fields:

FieldTypeDescription
ConnectionStringstringAzure Storage connection string
ContainerNamestringBlob container name
CreateContainerIfNotExistsboolAuto-create the container on startup (default: false)

Key dependency: Azure.Storage.Blobs

PropertyValue
Target frameworksnet8.0; net9.0
Supports resumable uploadsYes (block blob uncommitted blocks)
Supports presigned URLsYes (SAS tokens)

Vali-Blob.GCP

Google Cloud Storage provider implementation.

dotnet add package Vali-Blob.Core
dotnet add package Vali-Blob.GCP

What it provides:

  • GCPStorageProvider — full IStorageProvider + IResumableUploadProvider + IPresignedUrlProvider
  • GCPStorageOptions:
.AddProvider<GCPStorageProvider>("gcp", opts =>
{
opts.ProjectId = config["GCP:ProjectId"]!;
opts.BucketName = config["GCP:BucketName"]!;
opts.JsonCredentials = File.ReadAllText("/secrets/gcp-sa.json");
})

GCPStorageOptions fields:

FieldTypeDescription
ProjectIdstringGoogle Cloud project ID
BucketNamestringGCS bucket name
JsonCredentialsstring?Service account JSON (leave null to use Application Default Credentials)

Key dependency: Google.Cloud.Storage.V1

PropertyValue
Target frameworksnet8.0; net9.0
Supports resumable uploadsYes (GCS resumable upload sessions)
Supports presigned URLsYes (V4 signed URLs)

Vali-Blob.OCI

Oracle Cloud Infrastructure Object Storage provider.

dotnet add package Vali-Blob.Core
dotnet add package Vali-Blob.OCI

What it provides:

  • OCIStorageProviderIStorageProvider + IResumableUploadProvider
  • OCIStorageOptions — OCI tenancy OCID, region, bucket, and API key configuration

OCIStorageOptions fields:

FieldTypeDescription
TenancyIdstringOCI tenancy OCID
UserIdstringOCI user OCID
FingerprintstringAPI key fingerprint
PrivateKeystringPEM-encoded private key content
RegionstringOCI region identifier (e.g., us-ashburn-1)
BucketNamestringObject Storage bucket name
NamespacestringObject Storage namespace
PropertyValue
Target frameworksnet8.0; net9.0
Supports resumable uploadsYes (OCI multipart uploads)
Supports presigned URLsYes — via OCI Pre-Authenticated Requests (PARs). Unlike AWS/GCP, each URL requires an API call to OCI (no local signing).

Vali-Blob.Supabase

Supabase Storage provider implementation.

dotnet add package Vali-Blob.Core
dotnet add package Vali-Blob.Supabase

What it provides:

  • SupabaseStorageProviderIStorageProvider + IPresignedUrlProvider
  • SupabaseStorageOptions:
.AddProvider<SupabaseStorageProvider>("supabase", opts =>
{
opts.Url = config["Supabase:Url"]!; // https://xyz.supabase.co
opts.ServiceKey = config["Supabase:ServiceKey"]!; // service_role key
opts.BucketName = "user-uploads";
})

Key dependency: supabase-csharp

Resumable uploads with Supabase

SupabaseStorageProvider does not implement IResumableUploadProvider natively. For resumable uploads with Supabase, use Vali-Blob's own chunking layer by storing session state in Redis or EF Core and pointing the resumable upload endpoint at the Supabase provider.

PropertyValue
Target frameworksnet8.0; net9.0
Supports resumable uploadsNo (use Vali-Blob chunking layer)
Supports presigned URLsYes (signed URLs)

Vali-Blob.Local

Local filesystem storage provider for development and on-premise deployments.

dotnet add package Vali-Blob.Core
dotnet add package Vali-Blob.Local

What it provides:

  • LocalStorageProviderIStorageProvider + IResumableUploadProvider + IPresignedUrlProvider
  • LocalStorageOptions:
.AddProvider<LocalStorageProvider>("local", opts =>
{
opts.BasePath = Path.Combine(builder.Environment.ContentRootPath, "storage");
opts.CreateIfNotExists = true;
opts.PublicBaseUrl = "https://localhost:5001/storage";
})
  • Metadata stored as .meta.json sidecar files alongside each stored object
  • Resumable uploads via chunk staging directories under BasePath/.chunks/
  • Presigned URLs are signed HTTP URLs pointing to a local static files endpoint

LocalStorageOptions fields:

FieldTypeDefaultDescription
BasePathstringRequiredRoot directory for all stored files
CreateIfNotExistsboolfalseCreate BasePath if it does not exist
PublicBaseUrlstring?nullBase URL for generating public file URLs

Key dependency: None (pure .NET, no external SDK)

PropertyValue
Target frameworksnet8.0; net9.0
Supports resumable uploadsYes
Supports presigned URLsYes (local HTTP signed URLs)
External cloud dependencyNone

Vali-Blob.Redis

Redis-backed resumable upload session store.

dotnet add package Vali-Blob.Redis

What it provides:

  • RedisResumableSessionStore — implements IResumableSessionStore
  • RedisSessionStoreOptions — connection string, key prefix, and TTL
  • AddRedisSessionStore() DI extension
builder.Services
.AddVali-Blob(...)
.AddRedisSessionStore(opts =>
{
opts.ConnectionString = config["Redis:ConnectionString"]!;
opts.KeyPrefix = "valiblob:sessions:";
opts.Ttl = TimeSpan.FromHours(24);
});

When to use: Horizontally scaled applications (multiple instances) where resumable upload sessions must survive load balancer routing to different instances. Redis provides fast, shared session state with automatic expiry.

Key dependency: StackExchange.Redis

PropertyValue
Target frameworksnet8.0; net9.0
Minimum Redis version6.0
Session expiryConfigurable TTL (default: 24 hours)

Vali-Blob.EFCore

Entity Framework Core resumable upload session store.

dotnet add package Vali-Blob.EFCore

What it provides:

  • EfCoreResumableSessionStore — implements IResumableSessionStore
  • ResumableSessionDbContext — EF Core DbContext with ResumableSessions table
  • AddEfCoreSessionStore<TContext>() DI extension
  • EF Core migration support
// Register with your existing DbContext
builder.Services
.AddVali-Blob(...)
.AddEfCoreSessionStore<AppDbContext>();

// Or with the built-in standalone context
builder.Services
.AddDbContext<ResumableSessionDbContext>(o =>
o.UseNpgsql(config.GetConnectionString("Default")))
.AddEfCoreSessionStore<ResumableSessionDbContext>();

Apply the migration to create the sessions table:

dotnet ef migrations add AddResumableSessions
dotnet ef database update

When to use: Applications that already use EF Core and want sessions persisted to their existing relational database, with no need for a Redis cluster.

Key dependency: Microsoft.EntityFrameworkCore

Supported databases: PostgreSQL, MySQL, SQL Server, SQLite, and any EF Core provider.

PropertyValue
Target frameworksnet8.0; net9.0
Requires migrationYes
Supported databasesAny EF Core provider

Vali-Blob.Testing

In-memory storage provider for unit and integration tests.

dotnet add package Vali-Blob.Testing

What it provides:

  • InMemoryStorageProvider — in-process, dictionary-backed implementation of IStorageProvider and IResumableUploadProvider
  • Pre-seeding helpers for test setup:
var provider = new InMemoryStorageProvider();

// Seed a file with content
provider.Seed("uploads/avatar.jpg", Encoding.UTF8.GetBytes("fake-image-bytes"));

// Seed metadata
provider.SeedMetadata("uploads/avatar.jpg", new FileMetadata
{
SizeBytes = 1024,
ContentType = "image/jpeg"
});
  • Inspection helpers for assertions:
// Assert file was uploaded
Assert.True(provider.Contains("uploads/avatar.jpg"));

// Assert file content
var bytes = provider.GetBytes("uploads/avatar.jpg");
Assert.Equal(expectedBytes, bytes);

// Get all stored paths
var allPaths = provider.GetAll().Select(e => e.Path);

When to use: Every test project. The in-memory provider is deterministic, instantaneous, and requires no infrastructure. Inject it via DI using AddVali-Blob().AddProvider<InMemoryStorageProvider>("test").

Test isolation

Create a new InMemoryStorageProvider instance per test (or test class) to prevent state leakage between tests.

Key dependency: None (Vali-Blob.Core only)

PropertyValue
Target frameworksnet8.0; net9.0
Thread-safeYes
For production useNo — test projects only

Vali-Blob.HealthChecks

ASP.NET Core health check integration for storage providers.

dotnet add package Vali-Blob.HealthChecks

What it provides:

  • ValiBloBHealthCheck — implements IHealthCheck, probes a provider by calling ExistsAsync on a canary path
  • AddVali-Blob() extension on IHealthChecksBuilder
builder.Services
.AddHealthChecks()
.AddVali-Blob("aws-storage",
provider: serviceProvider => serviceProvider
.GetRequiredService<IStorageFactory>().Create("aws"),
failureStatus: HealthStatus.Unhealthy,
tags: ["storage", "aws"]);

app.MapHealthChecks("/health");

When to use: Any production ASP.NET Core application. Expose storage provider health via /health for Kubernetes liveness/readiness probes, uptime monitors, or operations dashboards.

Key dependency: Microsoft.Extensions.Diagnostics.HealthChecks

PropertyValue
Target frameworksnet8.0; net9.0
ASP.NET Core version8.0+

Vali-Blob.ImageSharp

Image processing pipeline middleware using SixLabors.ImageSharp.

dotnet add package Vali-Blob.ImageSharp

What it provides:

  • ImageProcessingMiddleware — upload-time image resize, format conversion, and thumbnail generation
  • ImageProcessingOptions — processing configuration
  • UseImageProcessing() pipeline extension method
.WithPipeline(p => p
.UseValidation(v => v.AllowedExtensions = [".jpg", ".png", ".webp"])
.UseImageProcessing(img =>
{
img.ResizeWidth = 1280;
img.ResizeHeight = 720;
img.OutputFormat = ImageFormat.WebP;
img.Quality = 85;
img.GenerateThumbnail = true;
img.ThumbnailWidth = 200;
img.ThumbnailHeight = 200;
})
.UseConflictResolution(ConflictResolution.ReplaceExisting)
)

ImageProcessingOptions fields:

FieldTypeDefaultDescription
ResizeWidthint?nullTarget width in pixels (null = no resize)
ResizeHeightint?nullTarget height in pixels (null = no resize)
OutputFormatImageFormat?nullConvert to this format (null = keep original)
Qualityint85JPEG/WebP quality (1–100)
GenerateThumbnailboolfalseAlso store a thumbnail
ThumbnailWidthint200Thumbnail width in pixels
ThumbnailHeightint200Thumbnail height in pixels
PropertyValue
Target frameworksnet8.0; net9.0
Supported input formatsJPEG, PNG, GIF, BMP, TIFF, WebP
Supported output formatsJPEG, PNG, WebP, AVIF
Key dependencySixLabors.ImageSharp