-
Notifications
You must be signed in to change notification settings - Fork 0
Quick Start
dotnet add package FileHub # core (Local + Memory)
dotnet add package FileHub.DependencyInjection # MS.Extensions.DI helpers
dotnet add package FileHub.AmazonS3 # AWS S3 driver
dotnet add package FileHub.OracleObjectStorage # OCI driver
dotnet add package FileHub.Ftp # FTP driver (FluentFTP)Targets netstandard2.0;net8.0. Core has zero external dependencies.
using FileHub.DependencyInjection;
using FileHub.Local;
services.AddFileHub<ILocalFileHub>(sp => new LocalFileHub(@"C:\data"));Then inject IFileHub (or the driver-typed ILocalFileHub) anywhere:
public class ReportService(IFileHub hub)
{
public void Save(string name, string body)
=> hub.Root.CreateFile(name).SetText(body);
}Backend-agnostic consumer code, driver decided at composition root. Swap to MemoryFileHub in tests, AmazonS3FileHub in prod — no service change. More patterns: Dependency injection.
For one-off scripts, console apps, or library code that doesn't run under a DI container:
using FileHub.Local;
var hub = new LocalFileHub(@"C:\data");
// hub.Root is the sandbox. Nothing outside C:\data is reachable.Root is a DirectoryEntry — everything else is reached from here.
// Create
var file = hub.Root.CreateFile("hello.txt");
file.SetText("hi");
// Nested path — auto-creates intermediate directories
hub.Root.CreateFile("reports/2026/q1.pdf").SetBytes(bytes);
// Read
var text = hub.Root.OpenFile("hello.txt").ReadAllText();
var bytes = hub.Root.OpenFile("payload.dat").ReadAllBytes();
// Existence — file vs directory probes are separate
if (hub.Root.FileExists("hello.txt")) { /* ... */ }
if (hub.Root.DirectoryExists("reports")) { /* ... */ }
// Streams
using var write = hub.Root.CreateFile("big.log").GetWriteStream();
using var read = hub.Root.OpenFile("big.log").GetReadStream();
// Non-throwing open
if (hub.Root.TryOpenFile("maybe.txt", out var f)) { /* ... */ }
// Async non-throwing open returns a tuple
var (maybe, exists) = await hub.Root.TryOpenFileAsync("maybe.txt", ct);
// Open-or-create
var cfg = hub.Root.OpenFile("config.json", createIfNotExists: true);// Single segment
var logs = hub.Root.CreateDirectory("logs");
// Nested path — works on every driver
var target = hub.Root.CreateDirectory("2026/01/invoices");
// Non-throwing open
if (hub.Root.TryOpenDirectory("2026/01", out var jan)) { /* ... */ }On cloud drivers the whole nested path resolves in a single API call — one PUT to create, one LIST to open.
foreach (var f in hub.Root.GetFiles("*.log"))
Console.WriteLine($"{f.Name}: {f.Length} bytes");
var file = hub.Root.OpenFile("report.pdf");
file.Rename("report-final.pdf"); // leaf name only — no '/' or '\'
file.MoveTo(hub.Root.CreateDirectory("archive"), "report-final.pdf"); // throws if the target name is taken
file.CopyTo("report-final.copy.pdf"); // throws if the copy name is taken
file.Delete(); // idempotent — no-op if already gone
hub.Root.DeleteIfExists("maybe.txt");
hub.Root.OpenDirectory("old").Delete(recursive: true); // non-empty dir needs recursive: truePagination options and caveats: Usage → Pagination.
Every sync method has an async sibling with a CancellationToken:
var file = await hub.Root.CreateFileAsync("data.json", ct);
await file.SetTextAsync("{}", cancellationToken: ct);
var json = await file.ReadAllTextAsync(ct);On net8.0, async listing yields one item at a time:
await foreach (var f in hub.Root.GetFilesAsync("*.log"))
Console.WriteLine(f.Name);var ro = hub.Root.OpenDirectory("config").AsReadOnly();
ro.OpenFile("settings.json").ReadAllText(); // OK
ro.CreateFile("new.txt"); // FileHubExceptionConsumer code depends on IFileHub / DirectoryEntry — the driver is a constructor detail:
IFileHub hub = isTest
? new MemoryFileHub()
: new LocalFileHub(@"C:\data");
void WriteReport(DirectoryEntry dir, string body)
=> dir.CreateFile("report.txt").SetText(body);
WriteReport(hub.Root, "hello");- API reference — every type in one page
-
Dependency injection —
AddFileHub+ named hubs + tenant scoping - Driver: Oracle Object Storage — cloud-specific setup and cost tuning
FileHub — unified file & directory API for .NET. Core is dependency-free; drivers are opt-in packages.