Local-filesystem implementation of IBlobService for .NET developers, storing blobs under a configured root folder
with path-traversal protection.
IBlobService in local development, unit tests, and CI with nothing to provision and nothing to clean
up but a folder.IBlobService consumers that run against S3 or Azure in production run
against a directory here; only the registration line differs.../ cannot reach outside it.dotnet new console -f net10.0 -n LocalBlobDemo
cd LocalBlobDemo
dotnet add package DKNet.Svc.BlobStorage.Local
dotnet add package Microsoft.Extensions.Logging
using DKNet.Svc.BlobStorage.Abstractions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
var config = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string?>
{
["BlobStorage:LocalFolder:RootFolder"] = Path.Combine(Path.GetTempPath(), "blob-demo")
})
.Build();
var services = new ServiceCollection().AddLogging().AddLocalDirectoryBlobService(config);
using var provider = services.BuildServiceProvider();
var blobService = provider.GetRequiredService<IBlobService>();
var location = await blobService.SaveAsync(
new BlobDetails.BlobData("reports/monthly.pdf", BinaryData.FromString("...")) { Overwrite = true });
Console.WriteLine(location); // reports/monthly.pdf
Run with dotnet run. AddLocalDirectoryBlobService(IServiceCollection, IConfiguration) binds
LocalDirectoryOptions from "BlobStorage:LocalFolder" and registers IBlobService → LocalBlobService as
Scoped; the call is idempotent.
There is no SDK client to build or cache here, unlike the cloud providers — every operation resolves a path under
RootFolder and touches the file system directly through System.IO.
Every operation resolves the requested name to an absolute path and re-checks it against the root before touching
the file system. The diagram does not show ListItemsAsync’s directory walk or SaveAsync’s overwrite/directory-
creation behavior — see the feature page below.
IBlobService contract, shared models, and validation that application code should depend on directly.