![]() |
VOOZH | about |
dotnet add package Stowage --version 2.0.1
NuGet\Install-Package Stowage -Version 2.0.1
<PackageReference Include="Stowage" Version="2.0.1" />
<PackageVersion Include="Stowage" Version="2.0.1" />Directory.Packages.props
<PackageReference Include="Stowage" />Project file
paket add Stowage --version 2.0.1
#r "nuget: Stowage, 2.0.1"
#:package Stowage@2.0.1
#addin nuget:?package=Stowage&version=2.0.1Install as a Cake Addin
#tool nuget:?package=Stowage&version=2.0.1Install as a Cake Tool
๐ Nuget
๐ Nuget (with prereleases)
๐ Nuget
This documentation is for Stowage v2 which is a major redesign. Version 1 documentation can be found .
Stowage is a bloat-free .NET cloud storage kit that supports at minimum THE major โ providers.
if()s? (or pattern matching).This library originally came out from being frustrated on working on my another library - Storage.Net. While it's OK, most of the time I had to deal with SDK incompatibilities, breaking changes, oddnesses, and slowness, whereas most of the time users needs something simple that just works.
Right, time to gear up. We'll do it step by step. First, you need to install the ๐ Nuget
package.
Simplest case, using the local ๐ฝ and writing text "I'm a page!!!" to a file called "pagefile.sys" at the root of disk C::
using Stowage;
using(IFileStorage fs = Files.Of.LocalDisk("c:\\")) {
await fs.WriteText("pagefile.sys", "I'm a page!!!!");
}
This is local disk, yeah? But what about cloud storage, like Azure Blob Storage? Piece of cake:
using Stowage;
using(IFileStorage fs = Files.Of.AzureBlobStorage("accountName", "accountKey", "containerName")) {
var entries = await fs.Ls();
}
Streaming is a first-class feature. This means the streaming is real with no workarounds or in-memory buffers, so you can upload/download files of virtually unlimited sizes. Most official SDKs do not support streaming at all - surprisingly even the cloud leader's .NET SDK doesn't. Each requires some sort of crippled down version of stream - either knowing length beforehand, or will buffer it all in memory. I don't. I stream like a stream.
Proper streaming support also means that you can transform streams as you write to them or read from them - something that is not available in the native SDKs. For instance gzipping, encryption, anything else.
Streaming is also truly compatible with synchronous and asynchronous API.
Whenever a method appears here, I assume it belongs to IFileStorage interface, unless specified.
Use .Ls() (short for list) - very easy to remember! Everyone knows what ls does, right? Optionally allows to list entries recursively.
The core method for reading is Stream OpenRead(IOPath path) - this returns a stream from file path. Stream is the lowest level data structure. There are other helper methods that by default rely on this method, like ReadText etc. Just have a quick look:
IFileStorage fs = ...;
Stream target = ...;
// copy to another stream
using Stream s = await fs.OpenRead("/myfile.txt");
// synchronous copy:
s.CopyTo(target);
// or alternatively, asynchronous copy (preferred):
await s.CopyToAsync(target);
// if you just need text:
string content = await fs.ReadText("/myfile.txt");
Of course there are more overloaded methods you can take advantage of.
The main method Stream OpenWrite(IOPath path, ...) opens(/creates?) a file for writing. It returns a real writeable stream you can write to and close afterwards. It behaves like a stream and is a stream.
There are other overloads which support writing text etc.
Rm(IOPath path) trashes files or folders (or both) with options to do it recursively!
There are other useful utility methods:
bool Exists(IOPath path) that checks for file existence. It supposed to be really efficient, hence a separate method.Ren renames files and folders.IFileStorage interface to be up to date.Local Disk Directory (Files.Of.LocalDisk(...)).
In-Memory (Files.Of.InternalMemory(...)).
AWS S3 (Files.Of.AmazonS3(...)).
Files.Of.Minio(...)).Files.Of.DigitalOceanSpaces(...)).Azure Blob Storage / Data Lake Gen 2 (Files.Of.AzureBlobStorage(...)).
Google Cloud Storage (Files.Of.GoogleCloudStorage(...)).
Databricks DBFS (Files.Of.DatabricksDbfs(...)).
Instantiation instructions are in the code documentation (IntelliSense?) - I prefer this to writing out here locally.
Below are some details worth mentioning.
In AWS, the path addressing style is the following:
/bucket/path/object
Ls on the root folder returns list of buckets in the AWS account, whether you do have access to them or not.
The most usual way to authenticate with S3 is to use the following method:
IFileStorage storage = Files.Of.AmazonS3(key, secret, region);
These are what Amazon calls "long-term" credentials. If you are using STS, the same method overload allows you to pass sessionToken.
Another way to authenticate is using CLI profile. This is useful when you machine is already authenticated using aws cli, awsume or similar tools that write credentials and configuration to ~/.aws/credentials and ~/.aws/config.
You only need to pass the profile name (and only if it's not a default one):
IFileStorage storage = Files.Of.AmazonS3FromCliProfile();
This method has other default parameters, such as regionName which can be specified or overridden if not found in CLI configuration.
Minio is essentially using the standard S3 protocol, but addressing style is slightly different. There is a helper extension that somewhat simplifies Minio authentication:
IFileStorage storage = Files.Of.Minio(endpoint, key, secret);
In Azure Blob Storage, path addressing style is the following:
/container/path/object
Note that there is no storage account in the path, mostly because Shared Key authentication is storage account scoped, not tenant scoped.
Ls on the root folder returns list of containers in the storage account.
Azure provider supports authentication with Shared Key:
IFileStorage storage = Files.Of.AzureBlobStorage(accountName, sharedKey);
Since v2, authentication with Entra Id service principals is supported too:
IFileStorage storage = Files.Of.AzureBlobStorage(
accountName,
new ClientSecretCredential(tenantId, clientId, clientSecret));
Interactive authentication with user credentials, and managed identities are not yet supported, but watch this space.
Azure emulator is supported, just use AzureBlobStorageWithLocalEmulator() method to connect to it.
There are many ways to extend functionality:
When contributing a new provider, it's way more preferrable to embed it's code in the library, provided that:
I'm a strong advocate of simplicity and not going to repeat the mistake of turning this into a nuget tree dependency hell!
You are welcome to contribute in any form, however I wouldn't bother, especially financially. Don't bother buying me a โ, I can do it myself real cheap. During my years of OSS development everyone I know (including myself) have only lost money. Why I'm still doing this? Probably because it's just cool and I'm enjoying it.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 net5.0 is compatible. net5.0-windows net5.0-windows was computed. net6.0 net6.0 is compatible. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
Showing the top 3 NuGet packages that depend on Stowage:
| Package | Downloads |
|---|---|
|
Packata.Storages
Packata is a library for consumming Data Package v2 files. The Packata.Storages package specializes in providing access to the package and resources wherever they are located (local file system, https(s), AWS S3 and Azure Data Lake Storage). |
|
|
FlowtideDotNet.Connector.DeltaLake
Package Description |
|
|
DeltaIO
Pure, managed, super fast Delta Lake implementation in .NET. |
Showing the top 1 popular GitHub repositories that depend on Stowage:
| Repository | Stars |
|---|---|
|
koralium/flowtide
High-performance streaming SQL query engine designed for real-time data processing. Use cases include event-driven architectures, ETL pipelines, and modern data-intensive applications.
|
| Version | Downloads | Last Updated |
|---|---|---|
| 2.1.0-pre.3 | 1,303 | 11/23/2024 |
| 2.1.0-pre.2 | 949 | 11/8/2024 |
| 2.1.0-pre.1 | 147 | 11/8/2024 |
| 2.0.2-pre.4 | 140 | 11/6/2024 |
| 2.0.2-pre.3 | 263 | 6/12/2024 |
| 2.0.2-pre.2 | 145 | 6/11/2024 |
| 2.0.2-pre.1 | 135 | 6/11/2024 |
| 2.0.1 | 62,007 | 5/31/2024 |
| 2.0.0 | 564 | 4/16/2024 |
| 2.0.0-pre.8 | 199 | 3/27/2024 |
| 2.0.0-pre.7 | 450 | 12/12/2023 |
| 2.0.0-pre.6 | 196 | 12/6/2023 |
| 2.0.0-pre.5 | 147 | 12/4/2023 |
| 2.0.0-pre.4 | 163 | 12/4/2023 |
| 2.0.0-pre.3 | 162 | 12/4/2023 |
| 2.0.0-pre.2 | 173 | 12/4/2023 |
| 2.0.0-pre.1 | 165 | 12/1/2023 |
| 1.5.1 | 801 | 11/23/2023 |
| 1.5.0 | 1,985 | 11/22/2023 |
| 1.4.0 | 263 | 11/15/2023 |