MinIO Storage with C#

MinIO is a high-performance, self-hosted object storage system that's S3-compatible.
I came across MinIO while looking fora self-hosted alternative to AWS S3. I needed a object storage that was lightweight and open source.
MinIO stood out because it has S3 API Compatbility while being simple to deploy with Docker.
In this guide, you'll learn how to:
- Install and run MinIO using Docker
- Set up a C# Minimal API
- Perform basic CRUD operations (upload, download, list, and delete objects)
- Understand the benefits of using MinIO
Prerequisites
Ensure you have the following installed:
- Docker
- .NET 8+ SDK
- A code editor (e.g., Visual Studio Code or Visual Studio)
Step 1: Running MinIO with Docker
Start MinIO using the following command:
docker run -p 9000:9000 -p 9001:9001 --name minio \
-e "MINIO_ROOT_USER=admin" \
-e "MINIO_ROOT_PASSWORD=admin123" \
-v $(pwd)/minio-data:/data \
quay.io/minio/minio server /data --console-address ":9001"
-
MinIO API: http://localhost:9000
-
Web Console: http://localhost:9001
-
Login Credentials:
-
Username: admin
-
Password: admin123
Step 2: Creating a C# Minimal API
Create a new Minimal API project:
# creates a new c# project
> dotnet new web -n MinIOApi
# navigates to the created folder
> cd MinIOApi
# adds the package MinIO to the project
> dotnet add package Minio
Open Program.cs and set up the API:
using Minio;
using Minio.DataModel.Args;
using System.IO;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
var minio = new MinioClient()
.WithEndpoint("http://localhost:9000")
.WithCredentials("admin", "admin123")
.WithSSL(false)
.Build();
app.MapGet("/", () => "Welcome to MinIO API");
app.Run();
Run the API and it will be accessible at http://localhost:5000.
Step 3: Implementing CRUD Operations
Code to Create a Bucket
app.MapPost("/create-bucket/{bucketName}", async (string bucketName) =>
{
await minio.MakeBucketAsync(new MakeBucketArgs().WithBucket(bucketName));
return Results.Ok($"Bucket '{bucketName}' created successfully.");
});
Code to Upload a File
app.MapPost("/upload/{bucketName}/{objectName}", async (string bucketName, string objectName, IFormFile file) =>
{
using var stream = file.OpenReadStream();
await minio.PutObjectAsync(new PutObjectArgs()
.WithBucket(bucketName)
.WithObject(objectName)
.WithStreamData(stream)
.WithObjectSize(file.Length)
);
return Results.Ok($"File '{objectName}' uploaded to bucket '{bucketName}'.");
});
Code Download a File
app.MapGet("/download/{bucketName}/{objectName}", async (string bucketName, string objectName) =>
{
var memoryStream = new MemoryStream();
await minio.GetObjectAsync(new GetObjectArgs()
.WithBucket(bucketName)
.WithObject(objectName)
.WithCallbackStream(async stream => await stream.CopyToAsync(memoryStream))
);
memoryStream.Position = 0;
return Results.File(memoryStream, "application/octet-stream", objectName);
});
Code to List Files in a Bucket
app.MapGet("/list/{bucketName}", async (string bucketName) =>
{
var objects = new List<string>();
await foreach (var obj in minio.ListObjectsAsync(new ListObjectsArgs().WithBucket(bucketName)))
{
objects.Add(obj.Key);
}
return Results.Ok(objects);
});
Code to Delete a File
app.MapDelete("/delete/{bucketName}/{objectName}", async (string bucketName, string objectName) =>
{
await minio.RemoveObjectAsync(new RemoveObjectArgs()
.WithBucket(bucketName)
.WithObject(objectName)
);
return Results.Ok($"File '{objectName}' deleted from bucket '{bucketName}'.");
});
Step 4: Testing the API
First start the API. dotnet run
Creating a bucket.
curl -X POST http://localhost:5000/create-bucket/my-bucket
Downloading a file.
curl -X GET http://localhost:5000/download/my-bucket/hello.txt -o hello.txt
Listing files.
curl -X GET http://localhost:5000/list/my-bucket
Deleting a file.
curl -X DELETE http://localhost:5000/delete/my-bucket/hello.txt
Benefits of Using MinIO
- Self-hosted and Lightweight & Ideal for local development and private cloud storage.
- S3 API Compatibility & Works seamlessly with AWS S3-compatible tools and libraries.
- High Performance & Optimized for fast object storage operations.
- Scalability & Supports both standalone and distributed deployments.
- Open-Source & No licensing fees, with strong community support.
Conclusion
We've successfully set up MinIO, built a C# Minimal API, and implemented CRUD operations for object storage.
This setup provides a powerful alternative to AWS S3, offering full control over your data in a self-hosted environment.