Means.Client
0.1.2
dotnet add package Means.Client --version 0.1.2
NuGet\Install-Package Means.Client -Version 0.1.2
<PackageReference Include="Means.Client" Version="0.1.2" />
<PackageVersion Include="Means.Client" Version="0.1.2" />
<PackageReference Include="Means.Client" />
paket add Means.Client --version 0.1.2
#r "nuget: Means.Client, 0.1.2"
#:package Means.Client@0.1.2
#addin nuget:?package=Means.Client&version=0.1.2
#tool nuget:?package=Means.Client&version=0.1.2
Means C# SDK
Standalone C# SDK for the Means S3-compatible object storage API. The package targets net8.0 and netstandard2.1, uses HttpClient, signs requests with SigV4, parses S3-style XML responses, and throws MeansError for S3-style XML errors.
Install from source
dotnet build SDKs/csharp/Means.Client.csproj -c Release
# or
dotnet pack SDKs/csharp/Means.Client.csproj -c Release
Release 构建或打包会在 SDKs/csharp/bin/Release 生成 Means.Client.0.1.2.nupkg 和 Means.Client.0.1.2.snupkg。
Reference the generated Means.Client package or project from your application.
Basic usage
For a runnable end-to-end sample, see ../examples/csharp-basic. It covers bucket creation, object upload/download, presigned GET/PUT URLs, versioning, lifecycle, and multipart upload.
using Means;
var client = new MeansClient(new MeansClientOptions
{
Endpoint = new Uri("http://localhost:5000"),
Credentials = new MeansCredentials("access-key", "secret-key"),
Region = "us-east-1",
ForcePathStyle = true
});
await client.CreateBucketAsync("photos");
await using var upload = File.OpenRead("image.jpg");
await client.PutObjectAsync(
"photos",
"2026/image.jpg",
upload,
contentType: "image/jpeg",
metadata: new Dictionary<string, string> { ["origin"] = "camera" });
var objects = await client.ListObjectsAsync("photos", prefix: "2026/");
await using var download = await client.GetObjectAsync("photos", "2026/image.jpg");
await using var file = File.Create("downloaded.jpg");
await download.Content.CopyToAsync(file);
API surface
MeansClientMeansClientOptionsMeansCredentialsBucketSummaryObjectSummaryBucketVersioningResultListObjectVersionsResultBucketLifecycleConfigurationObjectHeadResultPutObjectResultDeleteObjectResultCopyObjectResultCopyObjectOptionsObjectTaggingResultBucketXmlConfigurationResultMultipartUploadResultUploadPartResultCopyPartResultCompleteMultipartUploadResultListPartsResultListMultipartUploadsResultListMultipartUploadsOptionsPresignedRequestMeansError
MeansClient exposes PascalCase async methods for S3-compatible operations:
ListBucketsAsyncCreateBucketAsyncHeadBucketAsyncDeleteBucketAsyncGetBucketVersioningAsyncSetBucketVersioningAsyncListObjectVersionsAsyncGetBucketLifecycleAsyncPutBucketLifecycleAsyncDeleteBucketLifecycleAsyncGetBucketCorsAsyncPutBucketCorsAsyncDeleteBucketCorsAsyncGetBucketNotificationAsyncPutBucketNotificationAsyncDeleteBucketNotificationAsyncListObjectsAsyncPutObjectAsyncGetObjectAsyncHeadObjectAsyncDeleteObjectAsyncCopyObjectAsyncGetObjectTaggingAsyncPutObjectTaggingAsyncDeleteObjectTaggingAsyncInitiateMultipartUploadAsyncUploadPartAsyncUploadPartCopyAsyncCompleteMultipartUploadAsyncAbortMultipartUploadAsyncListPartsAsyncListMultipartUploadsAsyncUploadObjectMultipartAsyncCreatePresignedGetUrlAsyncCreatePresignedPutUrlAsyncCreatePresignedUploadPartUrlAsync
Synchronous presign helpers are also available as CreatePresignedGetUrl, CreatePresignedPutUrl, and CreatePresignedUploadPartUrl because URL signing does not perform I/O.
Multipart upload
await using var largeFile = File.OpenRead("large-video.mp4");
var completed = await client.UploadObjectMultipartAsync(
"photos",
"video/large-video.mp4",
largeFile,
contentType: "video/mp4");
Console.WriteLine(completed.ETag);
The high-level helper requires a readable, seekable stream, uses 16 MiB parts by default, and aborts the upload if a part or completion fails. Low-level multipart methods are available when callers need custom scheduling, UploadPartCopy, pagination, or presigned part URLs.
Versioning and lifecycle
await client.SetBucketVersioningAsync("photos", "Enabled");
var versions = await client.ListObjectVersionsAsync("photos", prefix: "2026/");
await using var oldVersion = await client.GetObjectAsync("photos", "2026/image.jpg", versions.Versions[0].VersionId);
await client.PutBucketLifecycleAsync("photos", new BucketLifecycleConfiguration
{
Rules =
{
new LifecycleRule
{
Id = "expire-logs",
Status = "Enabled",
Prefix = "logs/",
ExpirationDays = 30,
NoncurrentVersionExpirationDays = 7,
AbortIncompleteMultipartUploadDays = 1
}
}
});
Lifecycle day values must be positive integers. Empty lifecycle configurations are rejected; use DeleteBucketLifecycleAsync to remove rules.
Tagging, CORS, and notification
await client.PutObjectTaggingAsync(
"photos",
"2026/image.jpg",
new Dictionary<string, string> { ["kind"] = "raw" });
var tags = await client.GetObjectTaggingAsync("photos", "2026/image.jpg");
await client.PutBucketCorsAsync(
"photos",
"<CORSConfiguration><CORSRule><AllowedOrigin>*</AllowedOrigin><AllowedMethod>GET</AllowedMethod></CORSRule></CORSConfiguration>");
Bucket CORS and notification methods use raw XML so callers can pass through S3-compatible configuration variants without waiting for SDK model updates.
Presigned URLs
var presignedGet = client.CreatePresignedGetUrl(
"photos",
"2026/image.jpg",
TimeSpan.FromMinutes(15));
var versionedGet = client.CreatePresignedGetUrl(
"photos",
"2026/image.jpg",
versionId: "object-version-id",
expires: TimeSpan.FromMinutes(15));
Console.WriteLine(presignedGet.Url);
SigV4 presigned URLs require credentials and support expirations up to seven days.
Error handling
Means returns S3-style XML error envelopes. Non-success responses throw MeansError:
try
{
await client.HeadObjectAsync("photos", "missing.jpg");
}
catch (MeansError error) when (error.Code == "NoSuchKey")
{
Console.WriteLine(error.RequestId);
}
Addressing
Path-style addressing is enabled by default:
https://api.means.local/bucket/key
Set ForcePathStyle = false to use virtual-hosted-style addressing for DNS-compatible endpoints:
https://bucket.means.local/key
For the common Means layout where path-style requests go to api.means.local and virtual-hosted requests go to bucket.means.local, the SDK infers the suffix automatically. You can also set it explicitly:
ForcePathStyle = false,
VirtualHostedDomainSuffix = "means.local"
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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 was computed. 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 was computed. 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. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.