Skip to content

Repository files navigation

TagBites.IO

Nuget Targets License Downloads

TagBites.IO turns any storage into the same thing: a FileSystem browsed with FileLink and DirectoryLink. The local disk, an in-memory tree and a composed virtual tree are built in, and separate packages add FTP, SFTP, SMB, WebDAV, HTTP, ZIP, Dropbox, OneDrive, Google Cloud Storage, Azure Blob Storage and S3. An operation is written once - copy, move, sync, watch, restore a version - and runs wherever the files live, without a provider-specific SDK.

One API, any storage

Restore yesterday's FTP backup to disk:

using var ftp = FtpFileSystem.Create("ftp.example.com", "user", "password");

var backup = ftp.GetDirectory("/backups/2026-07-04");
var restore = FileSystem.Local.GetDirectory("C:/Restore");

backup.CopyTo(restore);

Turn an S3 bucket, a Dropbox account and a local folder into one Windows drive:

var s3 = S3FileSystem.Create(serviceUrl, accessKey, secretKey, "bucket");
var dropbox = DropboxFileSystem.Create(dropboxToken);

var backups = s3.GetDirectory("backups");
var photos = dropbox.GetDirectory("Photos");
var files = FileSystem.Local.GetDirectory("C:/Files");

var merged = new VirtualDirectory
{
    Entries =
    {
        new VirtualDirectoryEntry(backups, "S3"),
        new VirtualDirectoryEntry(photos, "Dropbox"),
        new VirtualDirectoryEntry(files, "Local")
    }
};

using var drive = new WinDrive(merged.ToDirectory()) { Name = "Merged Drive" };
drive.Mount(); // "V:\S3", "V:\Dropbox", "V:\Local"

Install

dotnet add package TagBites.IO

Targets netstandard2.0, netstandard2.1 and net5.0. No dependencies.

Local disk, an in-memory file system and a virtual composed tree are built in. Remote storages ship as separate packages that plug into the same API:

File system Package Storage
FileSystem.Local TagBites.IO Local disk (System.IO)
MemoryFileSystem.CreateMemory TagBites.IO In-memory tree, held for the lifetime of the instance
VirtualFileSystem TagBites.IO Several file systems composed into one tree
FtpFileSystem TagBites.IO.Ftp FTP / FTPS
SftpFileSystem TagBites.IO.Sftp SFTP
SmbFileSystem TagBites.IO.Smb SMB/CIFS network shares
WebDavFileSystem TagBites.IO.WebDav WebDAV
HttpFileSystem TagBites.IO.Http HTTP, read-only
ZipFileSystem TagBites.IO.Zip ZIP archives
DropboxFileSystem TagBites.IO.Dropbox Dropbox
OneDriveFileSystem TagBites.IO.OneDrive OneDrive (Microsoft Graph)
GoogleFileSystem TagBites.IO.Google Google Cloud Storage
AzureBlobFileSystem TagBites.IO.AzureBlob Azure Blob Storage
S3FileSystem TagBites.IO.S3 Amazon S3 and S3-compatible storage (e.g. Cloudflare R2)

and also allows to create custom file system.

TagBites.IO.WinDrive lets you mount any DirectoryLink - regardless of the underlying file system - as a real Windows drive letter.

Usage

var fs = FileSystem.Local;

var directory = fs.GetDirectory("/some/folder");
directory.Create();

var file = fs.GetFile("/some/folder/file.txt");
file.WriteAllText("Hello world!");

var content = file.ReadAllText(); // "Hello world!"

foreach (var f in directory.GetFiles(recursive: true))
    Console.WriteLine(f.FullName);

Every provider package (TagBites.IO.Ftp, TagBites.IO.S3, ...) exposes the same shape - a static Create(...) method returning a FileSystem - so the code above works unchanged regardless of the storage:

using var fs = FtpFileSystem.Create("ftp.example.com", "user", "password");
var file = fs.GetFile("/reports/2024/summary.csv");

Copy, move and sync

Source and destination can live in different storages:

using var ftp = FtpFileSystem.Create("ftp.example.com", "user", "password");
using var s3 = S3FileSystem.Create(serviceUrl, accessKey, secretKey, "archive");

var reports = ftp.GetDirectory("/reports");
var archive = s3.GetDirectory("/reports");

reports.Copy(archive, overwrite: true);
reports.Move(archive);
reports.SyncWith(archive, FileSystemSynchronizeMode.OneWayWithRemoveNotExisting);

What happens when the destination exists, and what happens when one file in a tree fails, is decided per call - see conflicts and errors.

Live synchronization

SyncWith runs once. FileSystemLinkSynchronizer keeps a pair in step for as long as it is enabled, across two different storages:

using var ftp = FtpFileSystem.Create("ftp.example.com", "user", "password");

var local = FileSystem.Local.GetDirectory("C:/Reports");
var remote = ftp.GetDirectory("/reports");

using var synchronizer = new FileSystemLinkSynchronizer();
synchronizer.Add(local, remote, FileSystemSynchronizeMode.BothWaysUsingLastWriteTime);

synchronizer.SyncFailed += (_, e) =>
    Console.WriteLine($"{e.Source.FullName}: {e.Exception.Message}, retry: {e.WillRetry}");

synchronizer.Enabled = true;

Change detection uses the same watcher the provider reports through FileSystemFeatures.Watcher. A storage without one notices only the changes made through the registered FileSystem instances, so call ForceSyncAsync() on a timer to catch what another client wrote:

await synchronizer.ForceSyncAsync();

See synchronization for what each mode does and what a watcher on a remote storage does not see.

File versions

A file system whose operations implement IFileSystemHistoryOperations exposes previous versions of a file:

var versions = file.GetHistoryVersions();

foreach (var version in versions)
    Console.WriteLine($"{version.ModifyTime} {version.Length}");

var previous = versions[0];

using var stream = previous.Read(); // the content of that version, without restoring it
previous.Restore();

No shipped provider implements file history yet. The API is there for a custom file system built over a storage that keeps versions - see file history and versioning.

Links

About

Unified, extensible file system abstraction for .NET - local, FTP, ZIP, WebDAV and cloud storage backends included, custom providers easy to implement.

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages