Persiltech.Storage.Minio 1.0.1

dotnet add package Persiltech.Storage.Minio --version 1.0.1
                    
NuGet\Install-Package Persiltech.Storage.Minio -Version 1.0.1
                    
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="Persiltech.Storage.Minio" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Persiltech.Storage.Minio" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="Persiltech.Storage.Minio" />
                    
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 Persiltech.Storage.Minio --version 1.0.1
                    
#r "nuget: Persiltech.Storage.Minio, 1.0.1"
                    
#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 Persiltech.Storage.Minio@1.0.1
                    
#: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=Persiltech.Storage.Minio&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=Persiltech.Storage.Minio&version=1.0.1
                    
Install as a Cake Tool

Persiltech.Storage.Minio

NuGet NuGet Downloads License: MIT .NET 8

MinIO object storage implementation for Persiltech.Storage.Abstractions. Provides a clean, type-safe abstraction over MinIO's .NET SDK with support for bucket management, file operations, presigned URLs, and access policies.

โœจ Features

  • ๐Ÿ”„ Complete CRUD Operations - Upload, download, delete, copy, move, and rename files
  • ๐Ÿ—‚๏ธ Bucket Management - Create, delete, and manage bucket access policies
  • ๐Ÿ”— Presigned URLs - Generate secure, time-limited URLs for file access
  • ๐Ÿ” Access Control - Support for private, public-read, and public-read-write policies
  • โšก Async/Await - Fully asynchronous API for optimal performance
  • ๐ŸŽฏ Strongly Typed - Type-safe configuration and operations
  • ๐Ÿ”Œ Dependency Injection - First-class DI support with IServiceCollection extensions
  • ๐ŸŒ Dual Endpoint Support - Separate internal and public endpoints for flexibility
  • ๐Ÿ“ Comprehensive Logging - Built-in logging with Microsoft.Extensions.Logging
  • ๐Ÿ›ก๏ธ Robust Error Handling - Detailed exceptions and rollback support

๐Ÿ“ฆ Installation

dotnet add package Persiltech.Storage.Minio

Or via Package Manager Console:

Install-Package Persiltech.Storage.Minio

๐Ÿš€ Quick Start

1. Configuration

Add MinIO settings to your appsettings.json:

{
  "ObjectStorageOptions": {
    "MinIO": {
      "Endpoint": "localhost:9000",
      "PublicEndpoint": "storage.yourdomain.com",
      "AccessKey": "your-access-key",
      "SecretKey": "your-secret-key",
      "WithSSL": true,
      "SkipCertificateValidation": false
    }
  }
}

2. Register Services

In your Program.cs or Startup.cs:

using Persiltech.Storage.Minio;

// Register MinIO storage
builder.Services.AddMinioStorage(builder.Configuration);

3. Use the Service

public class FileService
{
    private readonly MinioObjectStorageService _storage;
    
    public FileService(MinioObjectStorageService storage)
    {
        _storage = storage;
    }
    
    public async Task<string> UploadFileAsync(Stream fileStream, string fileName)
    {
        var url = await _storage.UploadFileAsync(
            stream: fileStream,
            container: "my-bucket",
            fileName: fileName,
            contentType: "application/octet-stream"
        );
        
        return url;
    }
}

๐Ÿ“š Detailed Usage Examples

File Operations

Upload a File
using var fileStream = File.OpenRead("document.pdf");

var fileUrl = await _storage.UploadFileAsync(
    stream: fileStream,
    container: "documents",
    fileName: "report-2025.pdf",
    contentType: "application/pdf"
);

Console.WriteLine($"File uploaded: {fileUrl}");
Download a File
var fileBytes = await _storage.DownloadFileAsync(
    container: "documents",
    fileName: "report-2025.pdf"
);

await File.WriteAllBytesAsync("downloaded-report.pdf", fileBytes);
Check if File Exists
bool exists = await _storage.FileExistsAsync(
    container: "documents",
    fileName: "report-2025.pdf"
);

if (exists)
{
    Console.WriteLine("File exists!");
}
Delete a File
await _storage.DeleteFileAsync(
    container: "documents",
    fileName: "old-report.pdf"
);
Copy a File
await _storage.CopyFileAsync(
    sourceContainer: "documents",
    sourceFileName: "report-2025.pdf",
    destContainer: "archive",
    destFileName: "report-2025-backup.pdf"
);
Move a File
await _storage.MoveFileAsync(
    sourceContainer: "temp",
    sourceFileName: "upload.pdf",
    destContainer: "documents",
    destFileName: "final-report.pdf"
);
Rename a File
await _storage.RenameFileAsync(
    container: "documents",
    oldFileName: "draft.pdf",
    newFileName: "final.pdf"
);

Presigned URLs

Generate secure, time-limited URLs for file access:

// Generate URL valid for 1 hour
var presignedUrl = await _storage.GeneratePresignedUrlAsync(
    container: "documents",
    fileName: "report-2025.pdf",
    expiry: TimeSpan.FromHours(1)
);

Console.WriteLine($"Download link: {presignedUrl}");

Bucket Management

Create a Bucket
using Persiltech.Storage.Abstractions;

// Create private bucket
await _storage.CreateContainerAsync(
    container: "private-docs",
    accessLevel: ContainerAccessLevel.Private
);

// Create public read-only bucket
await _storage.CreateContainerAsync(
    container: "public-images",
    accessLevel: ContainerAccessLevel.PublicRead
);
Check if Bucket Exists
bool bucketExists = await _storage.ContainerExistsAsync("my-bucket");
Set Bucket Access Policy
// Make bucket publicly readable
await _storage.SetContainerAccessPolicyAsync(
    container: "images",
    accessLevel: ContainerAccessLevel.PublicRead
);

// Make bucket private
await _storage.SetContainerAccessPolicyAsync(
    container: "sensitive-docs",
    accessLevel: ContainerAccessLevel.Private
);
Get Bucket Access Level
var accessLevel = await _storage.GetContainerAccessLevelAsync("my-bucket");

switch (accessLevel)
{
    case ContainerAccessLevel.Private:
        Console.WriteLine("Bucket is private");
        break;
    case ContainerAccessLevel.PublicRead:
        Console.WriteLine("Bucket is publicly readable");
        break;
    case ContainerAccessLevel.PublicReadWrite:
        Console.WriteLine("Bucket allows public read/write");
        break;
}
Delete a Bucket
// Note: Bucket must be empty
await _storage.DeleteContainerAsync("old-bucket");
Empty a Bucket
// Delete all files in a bucket
int deletedCount = await _storage.EmptyContainerAsync(
    container: "temp-uploads",
    progress: new Progress<int>(count => 
        Console.WriteLine($"Deleted {count} files...")
    )
);

Console.WriteLine($"Total files deleted: {deletedCount}");

โš™๏ธ Configuration Options

Option Type Required Description
Endpoint string Yes MinIO server endpoint (e.g., "localhost:9000")
PublicEndpoint string Yes Public-facing endpoint for presigned URLs
AccessKey string Yes MinIO access key
SecretKey string Yes MinIO secret key
WithSSL bool No Enable SSL/TLS (default: false)
SkipCertificateValidation bool No Skip SSL certificate validation (dev only!)

Dual Endpoint Configuration

The service supports separate internal and public endpoints:

  • Endpoint: Used for server-to-server communication (internal network)
  • PublicEndpoint: Used for presigned URLs accessible from the internet

Example:

{
  "Endpoint": "minio.internal.local:9000",
  "PublicEndpoint": "storage.example.com"
}

๐Ÿ” Security Considerations

SSL/TLS

Always enable SSL in production:

{
  "WithSSL": true,
  "SkipCertificateValidation": false
}

Certificate Validation

โš ๏ธ Never skip certificate validation in production! This option is only for development/testing:

{
  "SkipCertificateValidation": false  // Always false in production
}

Access Keys

Store sensitive credentials securely:

  • Use Azure Key Vault, AWS Secrets Manager, or similar
  • Use User Secrets for local development
  • Use Environment Variables in containers
  • Never commit credentials to source control

Example with User Secrets:

dotnet user-secrets set "ObjectStorageOptions:MinIO:AccessKey" "your-key"
dotnet user-secrets set "ObjectStorageOptions:MinIO:SecretKey" "your-secret"

๐Ÿงช Advanced Usage

Custom Container Names

// Using variables for container names
var bucketName = $"user-{userId}-uploads";
await _storage.CreateContainerAsync(bucketName);

Progress Reporting

var progress = new Progress<int>(count =>
{
    Console.WriteLine($"Processed: {count} files");
    // Update UI, send to SignalR, etc.
});

await _storage.EmptyContainerAsync("large-bucket", progress);

Error Handling

try
{
    await _storage.UploadFileAsync(stream, "bucket", "file.txt", "text/plain");
}
catch (ArgumentNullException ex)
{
    // Invalid parameters
    _logger.LogError(ex, "Invalid upload parameters");
}
catch (FileNotFoundException ex)
{
    // File not found (for operations like download)
    _logger.LogError(ex, "File not found");
}
catch (InvalidOperationException ex)
{
    // Operation failed (e.g., rollback failed in move)
    _logger.LogError(ex, "Operation failed");
}
catch (Exception ex)
{
    // General MinIO errors
    _logger.LogError(ex, "MinIO operation failed");
}

Cancellation Support

All methods support CancellationToken:

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));

try
{
    await _storage.UploadFileAsync(
        stream, 
        "bucket", 
        "file.txt", 
        "text/plain",
        cts.Token
    );
}
catch (OperationCanceledException)
{
    _logger.LogWarning("Upload cancelled");
}

๐Ÿ”„ Integration with Factory

Use with Persiltech.Storage.Factory for multi-cloud support:

// Install Factory package
dotnet add package Persiltech.Storage.Factory

// Register all storage providers
builder.Services.AddObjectStorage(builder.Configuration);

// Use the factory to get MinIO service
public class MyService
{
    private readonly IObjectStorageFactory _factory;
    
    public MyService(IObjectStorageFactory factory)
    {
        _factory = factory;
    }
    
    public async Task UseMinIO()
    {
        var storage = _factory.CreateService("minio");
        await storage.UploadFileAsync(...);
    }
}

๐Ÿ“‹ Requirements

  • .NET 10.0 or later
  • MinIO Server or any S3-compatible storage

Part of the Persiltech Storage family:

๐Ÿ“– Documentation

For more information:

๐Ÿ› Issues & Support

Found a bug or have a feature request?

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ‘ค Author

Edinson Aldaz - Persiltech

๐Ÿ™ Acknowledgments


Made with โค๏ธ by Persiltech

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 (1)

Showing the top 1 NuGet packages that depend on Persiltech.Storage.Minio:

Package Downloads
Persiltech.Storage.Factory

Factory pattern implementation for Persiltech Storage Libraries. Provides a unified interface to create and manage storage services across multiple cloud providers (MinIO, Azure Blob Storage, AWS S3). Supports provider switching at runtime and dependency injection integration. Simplifies multi-cloud storage architecture.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 118 5/5/2026
1.0.0 96 5/3/2026

v1.0.3 Release Notes:
     - Fixed resource leak in GeneratePresignedUrlAsync
     - Improved async/await pattern in DownloadFileAsync
     - Enhanced JSON policy parsing with System.Text.Json
     - Improved error handling with better rollback mechanism
     - Added comprehensive XML documentation
     - Performance improvements for concurrent operations