StorageProviders.Abstractions 1.0.35

dotnet add package StorageProviders.Abstractions --version 1.0.35
                    
NuGet\Install-Package StorageProviders.Abstractions -Version 1.0.35
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="StorageProviders.Abstractions" Version="1.0.35" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="StorageProviders.Abstractions" Version="1.0.35" />
                    
Directory.Packages.props
<PackageReference Include="StorageProviders.Abstractions" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add StorageProviders.Abstractions --version 1.0.35
                    
#r "nuget: StorageProviders.Abstractions, 1.0.35"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package StorageProviders.Abstractions@1.0.35
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=StorageProviders.Abstractions&version=1.0.35
                    
Install as a Cake Addin
#tool nuget:?package=StorageProviders.Abstractions&version=1.0.35
                    
Install as a Cake Tool

Storage Providers

Lint Code Base CodeQL License: MIT

A collection of Storage Providers for various destinations.

Azure Storage

NuGet Nuget

Installation

The library is available on NuGet. Search for StorageProviders.AzureStorage in the Package Manager GUI or run the following command in the .NET CLI:

dotnet add package StorageProviders.AzureStorage

How the library works

The package exposes the IStorageProvider abstraction, which offers a single asynchronous API for common file storage operations:

  • save content from byte[] or Stream
  • read content as Stream or byte[]
  • verify whether a file exists
  • enumerate files by prefix and extension
  • delete files
  • read file properties and metadata
  • update metadata
  • build the full file URI
  • generate a temporary read-only URI

The abstraction is designed so application code depends only on IStorageProvider, while the concrete provider can be registered through dependency injection.

IStorageProvider overview

The interface contains convenience overloads and stream-based methods:

  • SaveAsync supports uploads from both byte[] and Stream
  • ReadAsStreamAsync returns the file content as a stream
  • ReadAsByteArrayAsync is a convenience wrapper built on top of ReadAsStreamAsync
  • GetReadAccessUriAsync can optionally set a download file name when the provider supports it
  • EnumerateAsync returns an IAsyncEnumerable<string> so files can be streamed progressively
  • SetMetadataAsync updates the metadata associated with a file

Because the API is fully asynchronous, it works well in ASP.NET Core, background services, and other I/O-bound workloads.

Registering Azure Storage

The Azure implementation is provided by StorageProviders.AzureStorage and can be registered in two ways.

Static configuration

Use this overload when the Azure settings are known at startup:

builder.Services.AddAzureStorage(options =>
{
    options.ConnectionString = builder.Configuration.GetConnectionString("AzureStorageConnection")!;
    options.ContainerName = builder.Configuration.GetValue<string>("AppSettings:ContainerName");
});

This registration adds:

  • AzureStorageSettings as a singleton
  • IStorageProvider mapped to AzureStorageProvider as a singleton

Configuration resolved from the service provider

Use this overload when the storage settings depend on other registered services:

builder.Services.AddAzureStorage((serviceProvider, options) =>
{
    options.ConnectionString = serviceProvider
        .GetRequiredService<IConfiguration>()
        .GetConnectionString("AzureStorageConnection")!;

    options.ContainerName = serviceProvider
        .GetRequiredService<IConfiguration>()
        .GetValue<string>("AppSettings:ContainerName");
});

This registration adds:

  • AzureStorageSettings as scoped
  • IStorageProvider mapped to AzureStorageProvider as scoped

Azure provider behavior

AzureStorageProvider uses Azure Blob Storage and requires:

  • ConnectionString: the Azure Storage connection string
  • ContainerName: optional default container name

If ContainerName is configured, paths are treated as blob paths inside that container:

documents/report.pdf
images/logo.png

If ContainerName is not configured, the first segment of the path is interpreted as the container name:

documents/report.pdf   -> container: documents, blob: report.pdf
images/logo.png        -> container: images, blob: logo.png

Backslashes are normalized to forward slashes, so Windows-style paths are also accepted.

Main operations

Upload a file

using var stream = file.OpenReadStream();
await storageProvider.SaveAsync(file.FileName, stream, overwrite: false);

You can also upload metadata:

var metadata = new Dictionary<string, string>
{
    ["category"] = "invoice",
    ["customerId"] = "42"
};

using var stream = file.OpenReadStream();
await storageProvider.SaveAsync(file.FileName, stream, metadata, overwrite: true);

When overwrite is false, the Azure provider throws an IOException if the blob already exists.

Read a file

await using var stream = await storageProvider.ReadAsStreamAsync("documents/report.pdf");

Or read it as a byte array:

var content = await storageProvider.ReadAsByteArrayAsync("documents/report.pdf");

Check whether a file exists

var exists = await storageProvider.ExistsAsync("documents/report.pdf");

Enumerate files

await foreach (var path in storageProvider.EnumerateAsync("documents", [".pdf", ".docx"]))
{
    Console.WriteLine(path);
}

This method supports:

  • an optional prefix
  • filtering by extension
  • asynchronous streaming of results

Get file information

var fileInfo = await storageProvider.GetPropertiesAsync("documents/report.pdf");

The returned StorageFileInfo contains:

  • file name
  • inferred content type
  • size
  • creation date
  • last modification date
  • metadata

Update metadata

await storageProvider.SetMetadataAsync("documents/report.pdf", new Dictionary<string, string>
{
    ["category"] = "archived"
});

Passing null clears the existing metadata for the file.

Get the full blob URI

var uri = await storageProvider.GetFullPathAsync("documents/report.pdf");

Generate a temporary read URI

var uri = await storageProvider.GetReadAccessUriAsync(
    "documents/report.pdf",
    expirationDate: DateTime.UtcNow.AddMinutes(30),
    fileName: "Report.pdf");

For Azure Blob Storage this produces a SAS URI with read permissions. If a file name is provided, the provider also sets the Content-Disposition header so the browser can suggest a download name.

Delete a file

await storageProvider.DeleteAsync("documents/report.pdf");

Example with ASP.NET Core Minimal APIs

The sample project in samples/AzureStorageSample shows how to inject IStorageProvider in endpoints and use it for:

  • upload
  • upload with metadata
  • file existence checks
  • file listing
  • file download
  • metadata updates
  • file deletion
  • generating full and temporary read URIs

Example registration:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAzureStorage(options =>
{
    options.ConnectionString = builder.Configuration.GetConnectionString("AzureStorageConnection")!;
    options.ContainerName = builder.Configuration.GetValue<string>("AppSettings:ContainerName");
});

Example endpoint:

app.MapGet("/api/attachments/full-path", async (IStorageProvider storageProvider, string fileName) =>
{
    var fullPath = await storageProvider.GetFullPathAsync(fileName);
    return Results.Ok(fullPath);
});

Notes

  • The Azure provider automatically creates the target container when saving a file, if it does not exist.
  • Uploaded blobs use a content type inferred from the file name.
  • ReadAsStreamAsync and SetMetadataAsync throw when the target blob does not exist.
  • The API is storage-oriented and does not depend on ASP.NET Core, so it can also be used in console apps, workers, and class libraries.

Contribute

The project is constantly evolving. Contributions are welcome. Feel free to file issues and pull requests in the repository, and we'll address them as we can.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on StorageProviders.Abstractions:

Package Downloads
StorageProviders.AzureStorage

Storage Provider implementation that targets Azure Storage

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.35 73 4/15/2026
1.0.33 181 2/16/2026
1.0.20 441 11/13/2025
1.0.17 1,039 1/15/2025
1.0.16 625 4/4/2024
1.0.14 531 12/13/2023
1.0.13 605 4/12/2023
1.0.12 676 1/10/2023
1.0.10 544 12/27/2022
1.0.6 673 12/9/2022
1.0.3 554 12/5/2022