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
<PackageReference Include="Persiltech.Storage.Minio" Version="1.0.1" />
<PackageVersion Include="Persiltech.Storage.Minio" Version="1.0.1" />
<PackageReference Include="Persiltech.Storage.Minio" />
paket add Persiltech.Storage.Minio --version 1.0.1
#r "nuget: Persiltech.Storage.Minio, 1.0.1"
#:package Persiltech.Storage.Minio@1.0.1
#addin nuget:?package=Persiltech.Storage.Minio&version=1.0.1
#tool nuget:?package=Persiltech.Storage.Minio&version=1.0.1
Persiltech.Storage.Minio
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
๐ Related Packages
Part of the Persiltech Storage family:
- Persiltech.Storage.Abstractions - Core abstractions
- Persiltech.Storage.Factory - Multi-provider factory
- Persiltech.Storage.AzureBlob - Azure implementation
- Persiltech.Storage.S3 - AWS S3 implementation
๐ 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
- Built with Minio.NET SDK
- Powered by MinIO
Made with โค๏ธ by Persiltech
| 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
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.7)
- Minio (>= 7.0.0)
- Persiltech.Storage.Abstractions (>= 1.0.0)
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.
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