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
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Indiko.Blocks.Storage.S3" Version="4.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Indiko.Blocks.Storage.S3" Version="4.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Indiko.Blocks.Storage.S3" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Indiko.Blocks.Storage.S3 --version 4.0.0
                    
#r "nuget: Indiko.Blocks.Storage.S3, 4.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Indiko.Blocks.Storage.S3@4.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Indiko.Blocks.Storage.S3&version=4.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Indiko.Blocks.Storage.S3&version=4.0.0
                    
Install as a Cake Tool

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 (IFileProvider implementation)
  • AddS3Storage(configuration, logger) extension
  • S3StorageOptions

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 PutObject has no "fail if exists"; use ExistsAsync first when that matters.
  • CopyFileAsync / MoveFileAsync refuse an existing destination with ConflictException, matching the local provider. Copies run server-side; objects above 5 GiB are copied in parts. MoveFileAsync deletes 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 PresignedUrlExpiration short. SigV4 caps the lifetime at seven days, and a URL signed with temporary credentials dies with them.
  • UsePresignedUrls: false returns 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. VerifyBucketOnStartup only checks reachability.
  • ListFilesAndDirectoriesAsync pages 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 as AmazonS3Exception.

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:DeleteObject
  • s3:ListBucket for ListFilesAndDirectoriesAsync and VerifyBucketOnStartup
  • s3:AbortMultipartUpload for aborting a failed multipart transfer
  • kms:GenerateDataKey and kms:Decrypt when using KmsManagedKey

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
  • Indiko.Blocks.Storage.Abstractions
  • Indiko.Blocks.Storage.Local
  • Indiko.Blocks.Storage.AzureBlobStorage
Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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