Indiko.Blocks.Storage.S3
4.0.0
dotnet add package Indiko.Blocks.Storage.S3 --version 4.0.0
NuGet\Install-Package Indiko.Blocks.Storage.S3 -Version 4.0.0
<PackageReference Include="Indiko.Blocks.Storage.S3" Version="4.0.0" />
<PackageVersion Include="Indiko.Blocks.Storage.S3" Version="4.0.0" />
<PackageReference Include="Indiko.Blocks.Storage.S3" />
paket add Indiko.Blocks.Storage.S3 --version 4.0.0
#r "nuget: Indiko.Blocks.Storage.S3, 4.0.0"
#:package Indiko.Blocks.Storage.S3@4.0.0
#addin nuget:?package=Indiko.Blocks.Storage.S3&version=4.0.0
#tool nuget:?package=Indiko.Blocks.Storage.S3&version=4.0.0
Indiko.Blocks.Storage.S3
S3 implementation of IFileProvider, for Amazon S3 and S3-compatible object storage.
Overview
This package stores files as objects in a bucket. It works against Amazon S3 and against S3-compatible services such as MinIO, Ceph RGW, Wasabi, Cloudflare R2 and Backblaze B2. Uploads and downloads stream instead of being buffered in memory, and large uploads are split into a multipart transfer automatically.
Key Components
S3StorageBlock(block entry point)S3StorageFileProvider(IFileProviderimplementation)AddS3Storage(configuration, logger)extensionS3StorageOptions
DI Registration Entry Points
S3StorageBlock.ConfigureServices(...)services.AddS3Storage(configuration, logger)
Registers IAmazonS3 and ITransferUtility as singletons and IFileProvider as scoped.
Configuration
Configuration section: S3StorageOptions
| Setting | Default | Purpose |
|---|---|---|
Enabled |
false |
Activates the block. |
MaxFileSize |
100 |
Largest accepted upload, in megabytes. |
AllowedFileTypes |
— | Accepted extensions. An empty list rejects every upload. |
BucketName |
— | Required. The bucket. |
Folder |
— | Key prefix acting as the folder every operation is relative to. |
Region |
— | AWS region, e.g. eu-central-1. |
ServiceUrl |
— | Endpoint of an S3-compatible service. Empty for Amazon S3. |
ForcePathStyle |
unset | Bucket in the path instead of the hostname. Unset = on for ServiceUrl, off for AWS. |
AccessKey / SecretKey / SessionToken |
— | Static credentials. Leave empty for the AWS default credential chain. |
UsePresignedUrls |
true |
Whether GetFullPathAsync returns a signed URL. |
PresignedUrlExpiration |
15 |
Validity of signed URLs, in minutes. |
ServerSideEncryption |
None |
None, AwsManagedKey (SSE-S3) or KmsManagedKey (SSE-KMS). |
KmsKeyId |
— | Required for KmsManagedKey. |
MultipartPartSize |
8 |
Part size for multipart uploads, in megabytes (minimum 5). |
UseAccelerateEndpoint |
false |
S3 Transfer Acceleration. Amazon S3 only, bills extra. |
MaxErrorRetry |
3 |
Retries per request. |
TimeoutSeconds |
100 |
Per-request timeout. |
VerifyBucketOnStartup |
false |
Check at startup that the bucket is reachable. |
Amazon S3 with an IAM role
{
"S3StorageOptions": {
"Enabled": true,
"BucketName": "my-app-documents",
"Folder": "invoices",
"Region": "eu-central-1",
"MaxFileSize": 25,
"AllowedFileTypes": [ ".pdf", ".png" ],
"ServerSideEncryption": "AwsManagedKey"
}
}
No credentials in the configuration: the SDK resolves them from the environment, the ECS task role, IRSA on EKS or the EC2 instance profile. That is the recommended setup on AWS, because those credentials rotate on their own.
MinIO or another S3-compatible service
{
"S3StorageOptions": {
"Enabled": true,
"BucketName": "documents",
"ServiceUrl": "https://minio.internal:9000",
"Region": "us-east-1",
"AccessKey": "...",
"SecretKey": "...",
"MaxFileSize": 100,
"AllowedFileTypes": [ ".pdf", ".png", ".zip" ]
}
}
ForcePathStyle defaults to on for a custom ServiceUrl. Region is still worth setting:
several compatible services need it for request signing.
Minimal Usage
var provider = serviceProvider.GetRequiredService<IFileProvider>();
// Upload, streaming -- the payload is never held in memory in full
await using var file = File.OpenRead("invoice.pdf");
var fileName = await provider.SaveFileAsync(".pdf", "invoice-2026-001.pdf", file, cancellationToken);
// Hand out a link valid for 15 minutes
var url = await provider.GetFullPathAsync(fileName, cancellationToken);
// Download, streaming
await using var download = await provider.OpenReadAsync(fileName, cancellationToken);
Runtime Behavior and Caveats
SaveFileAsync(fileExtension, content)expects Base64, like the Azure Blob Storage provider. The local provider stores the same argument as raw text, so this overload is not portable -- prefer a stream overload.- Uploads overwrite. S3
PutObjecthas no "fail if exists"; useExistsAsyncfirst when that matters. CopyFileAsync/MoveFileAsyncrefuse an existing destination withConflictException, matching the local provider. Copies run server-side; objects above 5 GiB are copied in parts.MoveFileAsyncdeletes the source only after the copy has completed -- an interruption leaves both copies, never neither.- A pre-signed URL is a bearer token. Anyone holding it can read the object until it
expires, and it cannot be revoked. Keep
PresignedUrlExpirationshort. SigV4 caps the lifetime at seven days, and a URL signed with temporary credentials dies with them. UsePresignedUrls: falsereturns the plain object URL, which only works on a public bucket or behind a CDN that signs requests itself.- The size limit on a non-seekable stream is enforced mid-transfer. A request body has no known length, so the upload is aborted once the limit is passed and the partial object is removed. A seekable stream is rejected before anything is sent.
- The bucket is never created. Creation carries decisions (region, versioning, lifecycle,
public access block) that do not belong in application startup.
VerifyBucketOnStartuponly checks reachability. ListFilesAndDirectoriesAsyncpages to the end. A prefix holding many objects produces many requests and a large result.- Thrown exceptions:
ConfigurationException(bucket missing or unreachable, invalid configuration),NotFoundException,ConflictException,NotAllowedException(extension not allowed, invalid file name, non-Base64 content),LimitExceededException. Other S3 failures surface asAmazonS3Exception.
Only One Storage Block Per Application
Every storage block registers IFileProvider under the same contract, and block discovery
resolves one IStorageBlock. Reference Indiko.Blocks.Storage.S3 or .Local or
.AzureBlobStorage, not several at once.
IAM Permissions
The minimum for normal operation on the configured prefix:
s3:PutObject,s3:GetObject,s3:DeleteObjects3:ListBucketforListFilesAndDirectoriesAsyncandVerifyBucketOnStartups3:AbortMultipartUploadfor aborting a failed multipart transferkms:GenerateDataKeyandkms:Decryptwhen usingKmsManagedKey
A lifecycle rule for incomplete multipart uploads is worth having: parts of an upload that was never completed or aborted stay billable.
Target Framework
- .NET 10
Related Packages
Indiko.Blocks.Storage.AbstractionsIndiko.Blocks.Storage.LocalIndiko.Blocks.Storage.AzureBlobStorage
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- AWSSDK.S3 (>= 4.0.104)
- Indiko.Blocks.Storage.Abstractions (>= 4.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.0.0 | 44 | 10/1/2026 |