Kemenkeu.Repository.File
1.0.0
dotnet add package Kemenkeu.Repository.File --version 1.0.0
NuGet\Install-Package Kemenkeu.Repository.File -Version 1.0.0
<PackageReference Include="Kemenkeu.Repository.File" Version="1.0.0" />
<PackageVersion Include="Kemenkeu.Repository.File" Version="1.0.0" />
<PackageReference Include="Kemenkeu.Repository.File" />
paket add Kemenkeu.Repository.File --version 1.0.0
#r "nuget: Kemenkeu.Repository.File, 1.0.0"
#:package Kemenkeu.Repository.File@1.0.0
#addin nuget:?package=Kemenkeu.Repository.File&version=1.0.0
#tool nuget:?package=Kemenkeu.Repository.File&version=1.0.0
Kemenkeu.Repository.File
Kemenkeu.Repository.File is a file repository library for MinIO that provides simple and clean abstractions for file storage operations. It supports Store, Get, and Remove operations with configurable bucket and folder path settings.
Features
- Store files to MinIO object storage
- Get files as streams or with callback processing
- Remove files from storage
- Configurable bucket and folder path prefixes
- Built-in error handling and logging
- Multi-framework support (.NET 6, 7, 8, 9, 10)
- Configurable via
appsettings.jsonor code - Support for SSL/TLS connections
Installation
Install the library via NuGet:
dotnet add package Kemenkeu.Repository.File
Configuration
appsettings.json Configuration
Add the following configuration to your appsettings.json file:
{
"MinIO": {
"Endpoint": "localhost:9000",
"AccessKey": "minioadmin",
"SecretKey": "minioadmin",
"UseSSL": false,
"Region": "us-east-1",
"BucketName": "my-bucket",
"FolderPath": "documents"
}
}
Configuration Options
| Option | Type | Description | Required |
|---|---|---|---|
Endpoint |
string | MinIO endpoint URL (e.g., "localhost:9000") | Yes |
AccessKey |
string | Access key for MinIO authentication | Yes |
SecretKey |
string | Secret key for MinIO authentication | Yes |
UseSSL |
bool | Use SSL/TLS for connection | No (default: false) |
Region |
string | Region for MinIO | No |
BucketName |
string | Bucket name where files will be stored | No (default: "default") |
FolderPath |
string | Optional folder path prefix for all files | No |
Usage
1. Setup in Program.cs (.NET 6+)
using Kemenkeu.Repository.File.Extensions;
var builder = WebApplication.CreateBuilder(args);
// Option 1: Configure from appsettings.json
builder.Services.AddFileRepository(builder.Configuration);
// Option 2: Configure with options object
var minioSettings = builder.Configuration.GetSection("MinIO").Get<MinioSettings>();
builder.Services.AddFileRepository(minioSettings);
// Option 3: Configure with action
builder.Services.AddFileRepository(options =>
{
options.Endpoint = "localhost:9000";
options.AccessKey = "minioadmin";
options.SecretKey = "minioadmin";
options.UseSSL = false;
options.BucketName = "my-bucket";
options.FolderPath = "documents";
});
var app = builder.Build();
app.Run();
2. Using the File Repository
using Kemenkeu.Repository.File.Abstractions;
public class DocumentService
{
private readonly IFileRepository _fileRepository;
private readonly ILogger<DocumentService> _logger;
public DocumentService(
IFileRepository fileRepository,
ILogger<DocumentService> logger)
{
_fileRepository = fileRepository;
_logger = logger;
}
// Store a file
public async Task UploadDocumentAsync(string fileName, Stream fileStream)
{
await _fileRepository.Store(fileName, fileStream);
_logger.LogInformation("Document {FileName} uploaded successfully", fileName);
}
// Get a file as stream
public async Task<Stream?> DownloadDocumentAsync(string fileName)
{
var stream = await _fileRepository.Get(fileName);
if (stream == null)
{
_logger.LogWarning("Document {FileName} not found", fileName);
return null;
}
return stream;
}
// Get a file with callback processing
public async Task ProcessDocumentAsync(string fileName)
{
await _fileRepository.Get(fileName, stream =>
{
// Process the stream directly without loading into memory
using var reader = new StreamReader(stream);
var content = reader.ReadToEnd();
_logger.LogInformation("Document content length: {Length}", content.Length);
});
}
// Remove a file
public async Task DeleteDocumentAsync(string fileName)
{
await _fileRepository.Remove(fileName);
_logger.LogInformation("Document {FileName} deleted successfully", fileName);
}
// Get full path (with folder prefix)
public string GetFullPath(string relativePath)
{
return _fileRepository.GetPath(relativePath);
}
}
3. Controller Example
using Kemenkeu.Repository.File.Abstractions;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class DocumentsController : ControllerBase
{
private readonly IFileRepository _fileRepository;
public DocumentsController(IFileRepository fileRepository)
{
_fileRepository = fileRepository;
}
[HttpPost("upload")]
public async Task<IActionResult> Upload(IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest("No file uploaded");
using var stream = file.OpenReadStream();
await _fileRepository.Store(file.FileName, stream);
return Ok(new { message = "File uploaded successfully", fileName = file.FileName });
}
[HttpGet("download/{fileName}")]
public async Task<IActionResult> Download(string fileName)
{
var stream = await _fileRepository.Get(fileName);
if (stream == null)
return NotFound($"File {fileName} not found");
return File(stream, "application/pdf", fileName);
}
[HttpDelete("{fileName}")]
public async Task<IActionResult> Delete(string fileName)
{
await _fileRepository.Remove(fileName);
return Ok(new { message = "File deleted successfully", fileName });
}
}
Advanced Usage
Custom Content Types
The default implementation uses application/pdf as the content type. To support different content types, you can extend the FileRepository class:
public class CustomFileRepository : FileRepository
{
public CustomFileRepository(
ILogger<FileRepository> logger,
IMinioClient minioClient,
IOptions<MinioSettings> minioSettings)
: base(logger, minioClient, minioSettings)
{
}
public async Task Store(string path, Stream stream, string contentType)
{
// Override Store method to accept custom content type
path = GetPath(path);
var putObjectArgs = new PutObjectArgs()
.WithBucket(_bucketName)
.WithObject(path)
.WithStreamData(stream)
.WithObjectSize(stream.Length)
.WithContentType(contentType);
await _minioClient.PutObjectAsync(putObjectArgs);
}
}
Error Handling
The repository handles ObjectNotFoundException gracefully:
public async Task<Stream?> SafeGet(string fileName)
{
try
{
return await _fileRepository.Get(fileName);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error retrieving file {FileName}", fileName);
return null;
}
}
Best Practices
- Use Folder Paths: Organize files using the
FolderPathconfiguration to group related files - Stream Processing: Use the callback-based
Getmethod for large files to avoid loading them entirely into memory - Error Handling: Always check for null returns when using
Getmethod - Content Types: Consider extending the repository to support different content types based on file extensions
- Bucket Management: Ensure buckets are created before storing files
- Path Validation: Validate file paths before storing to prevent security issues
Troubleshooting
Connection Issues
- Ensure the MinIO endpoint is correct and accessible
- Verify access key and secret key credentials
- Check network connectivity to MinIO server
- For SSL connections, ensure certificates are properly configured
File Not Found Errors
- Verify the file path is correct (including folder prefix if configured)
- Check that the file exists in the specified bucket
- Ensure the bucket name is correct
Upload Failures
- Verify the bucket exists and is accessible
- Check file size limits
- Ensure the stream is readable and positioned correctly
- Verify permissions for the access key
License
This project is licensed under the MIT License.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. 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 is compatible. 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 is compatible. 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 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.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.0)
- Minio (>= 5.0.2)
-
net6.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.0)
- Minio (>= 5.0.2)
-
net7.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.0)
- Minio (>= 5.0.2)
-
net8.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.0)
- Minio (>= 5.0.2)
-
net9.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options (>= 8.0.0)
- Minio (>= 5.0.2)
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 |
|---|---|---|
| 1.0.0 | 254 | 12/4/2025 |