minio-d ~main
MinIO client library for D, using vibe.d
To use this package, run the following command in your project's root directory:
Manual usage
Put the following dependency into your project's dependences section:
MinIO / S3 Object Storage
A MinIO / S3-compatible object storage client library for the D programming language, built on vibe.d.
Supports bucket management, object CRUD, listing with pagination, presigned URLs, and SigV4 authentication.
Table of Contents
- Installation
- Quick Start
- Client Construction
- Explicit credentials
- From environment variables
- With TLS
- Bucket Operations
- listBuckets
- createBucket
- bucketExists
- Object Operations
- putObject
- uploadFile
- getObject
- getObject (streaming)
- downloadFile
- headObject
- deleteObject
- Listing Objects
- listObjects
- listAllObjects
- Presigned URLs
- presignedGetUrl
- presignedPutUrl
- Types
- Error Handling
- Compatibility
- License
Installation
Add to your dub.sdl:
dependency "minio-d" version="~>1.0.0"
Or dub.json:
"dependencies": {
"minio-d": "~>1.0.0"
}
Quick Start
import minio;
import std.stdio;
void main()
{
// Connect to MinIO
auto client = new MinioClient("localhost:9000", "minioadmin", "minioadmin");
// Create a bucket
if (!client.bucketExists("my-bucket"))
client.createBucket("my-bucket");
// Upload data
auto data = cast(const(ubyte)[]) "Hello, MinIO!";
client.putObject("my-bucket", "greeting.txt", data, "text/plain");
// Download and print
auto result = client.getObject("my-bucket", "greeting.txt");
writeln(cast(string) result.data);
// Output: Hello, MinIO!
// Clean up
client.deleteObject("my-bucket", "greeting.txt");
}
Client Construction
Explicit credentials
auto client = new MinioClient(
"localhost:9000", // endpoint
"minioadmin", // access key
"minioadmin", // secret key
false, // useTLS (default: false)
"us-east-1" // region (default: "us-east-1")
);
From environment variables
Reads MINIO_ACCESS_KEY / MINIO_SECRET_KEY (or AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY):
auto creds = envCredentials();
auto client = new MinioClient("localhost:9000", creds);
With TLS
auto client = new MinioClient("s3.example.com", "key", "secret", true);
Bucket Operations
listBuckets
auto buckets = client.listBuckets();
foreach (b; buckets)
writeln(b.name, " created ", b.creationDate);
// Output:
// my-bucket created 2026-03-15T10:30:00.000Z
// backups created 2026-01-01T00:00:00.000Z
createBucket
client.createBucket("new-bucket");
bucketExists
if (client.bucketExists("my-bucket"))
writeln("Bucket exists");
else
writeln("Bucket not found");
// Output: Bucket exists
Object Operations
putObject
Upload raw bytes with a content type:
auto data = cast(const(ubyte)[]) "file contents here";
client.putObject("my-bucket", "docs/readme.txt", data, "text/plain");
uploadFile
Upload a file from disk:
client.uploadFile("my-bucket", "images/photo.jpg", "/path/to/photo.jpg", "image/jpeg");
getObject
Download an object into memory:
auto result = client.getObject("my-bucket", "docs/readme.txt");
writeln("Content-Type: ", result.contentType);
writeln("Size: ", result.contentLength, " bytes");
writeln("ETag: ", result.etag);
writeln("Content: ", cast(string) result.data);
// Output:
// Content-Type: text/plain
// Size: 18 bytes
// ETag: "d3b07384d113edec49eaa6238ad5ff00"
// Content: file contents here
Custom metadata is available via result.metadata:
foreach (key, value; result.metadata)
writeln("x-amz-meta-", key, ": ", value);
getObject (streaming)
Process the response without buffering the entire body:
client.getObject("my-bucket", "large-file.bin", (scope HTTPClientResponse resp) {
auto reader = resp.bodyReader;
// process reader stream...
});
downloadFile
Download an object directly to a file on disk:
client.downloadFile("my-bucket", "images/photo.jpg", "/tmp/photo.jpg");
import std.file : getSize;
writeln("Downloaded: ", getSize("/tmp/photo.jpg"), " bytes");
// Output: Downloaded: 245832 bytes
headObject
Get object metadata without downloading the body:
auto head = client.headObject("my-bucket", "docs/readme.txt");
writeln("Content-Type: ", head.contentType);
writeln("Size: ", head.contentLength);
writeln("ETag: ", head.etag);
writeln("Last-Modified: ", head.lastModified);
// Output:
// Content-Type: text/plain
// Size: 18
// ETag: "d3b07384d113edec49eaa6238ad5ff00"
// Last-Modified: Fri, 28 Mar 2026 14:30:00 GMT
deleteObject
client.deleteObject("my-bucket", "docs/readme.txt");
Listing Objects
listObjects
List objects with optional prefix, delimiter, and pagination:
// List all objects in a bucket
auto result = client.listObjects("my-bucket");
foreach (obj; result.objects)
writeln(obj.key, " ", obj.size, " bytes");
// Output:
// docs/readme.txt 18 bytes
// images/photo.jpg 245832 bytes
// images/logo.png 12048 bytes
With prefix filter:
// List only objects under images/
auto result = client.listObjects("my-bucket", "images/");
foreach (obj; result.objects)
writeln(obj.key, " ", obj.size, " bytes");
// Output:
// images/photo.jpg 245832 bytes
// images/logo.png 12048 bytes
With delimiter for directory-like listing:
// List "directories" at root level
auto result = client.listObjects("my-bucket", null, "/");
foreach (prefix; result.commonPrefixes)
writeln("DIR ", prefix);
foreach (obj; result.objects)
writeln("FILE ", obj.key, " ", obj.size, " bytes");
// Output:
// DIR docs/
// DIR images/
With custom page size:
// Fetch only 10 objects per request
auto page = client.listObjects("my-bucket", null, null, 10);
writeln("Got ", page.objects.length, " objects, more: ", page.isTruncated);
// Output: Got 10 objects, more: true
Manual pagination:
string token = null;
int total = 0;
while (true)
{
auto page = client.listObjects("my-bucket", null, null, 100, token);
total += page.objects.length;
if (!page.isTruncated)
break;
token = page.nextContinuationToken;
}
writeln("Total objects: ", total);
// Output: Total objects: 1523
listAllObjects
Automatically fetches all pages:
auto result = client.listAllObjects("my-bucket", "images/");
writeln("Total images: ", result.objects.length);
foreach (obj; result.objects)
writeln(" ", obj.key, " ", obj.size, " bytes");
// Output:
// Total images: 3
// images/logo.png 12048 bytes
// images/photo.jpg 245832 bytes
// images/banner.webp 98400 bytes
Presigned URLs
Generate temporary URLs for direct client access without credentials.
presignedGetUrl
import core.time : seconds;
// Default expiry: 1 hour
auto url = client.presignedGetUrl("my-bucket", "images/photo.jpg");
writeln(url);
// Output: http://localhost:9000/my-bucket/images/photo.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&...
// Custom expiry: 5 minutes
auto shortUrl = client.presignedGetUrl("my-bucket", "images/photo.jpg", 300.seconds);
presignedPutUrl
auto url = client.presignedPutUrl("my-bucket", "uploads/new-file.bin", 600.seconds);
writeln(url);
// Output: http://localhost:9000/my-bucket/uploads/new-file.bin?X-Amz-Algorithm=AWS4-HMAC-SHA256&...
Types
S3Object
struct S3Object
{
string key; // Object key (path)
string etag; // MD5 hash of content
ulong size; // Size in bytes
string lastModified; // ISO 8601 timestamp
string storageClass; // e.g. "STANDARD"
}
GetObjectResult
struct GetObjectResult
{
ubyte[] data; // Object body
string contentType; // MIME type
ulong contentLength; // Size in bytes
string etag; // MD5 hash
string[string] metadata; // Custom x-amz-meta-* headers
}
HeadObjectResult
struct HeadObjectResult
{
string contentType;
ulong contentLength;
string etag;
string lastModified;
string[string] metadata;
}
ListObjectsResult
struct ListObjectsResult
{
S3Object[] objects; // Objects in this page
string[] commonPrefixes; // "Directory" prefixes (when using delimiter)
bool isTruncated; // More pages available
string nextContinuationToken; // Token for next page
}
BucketInfo
struct BucketInfo
{
string name;
string creationDate;
}
Error Handling
Operations throw MinioException on failure:
try
{
auto result = client.getObject("my-bucket", "nonexistent.txt");
}
catch (MinioException e)
{
writeln("Status: ", e.statusCode); // 404
writeln("Code: ", e.errorCode); // "NoSuchKey"
writeln("Message: ", e.msg); // "NoSuchKey (404): The specified key does not exist."
}
Common error codes:
| Status | Code | Meaning |
|---|---|---|
| 404 | NoSuchKey | Object not found |
| 404 | NoSuchBucket | Bucket not found |
| 403 | AccessDenied | Invalid credentials or permissions |
| 409 | BucketAlreadyOwnedByYou | Bucket already exists |
| 400 | InvalidBucketName | Invalid bucket name |
Compatibility
Works with:
- MinIO (primary target)
- Amazon S3
- Any S3-compatible storage (Backblaze B2, Wasabi, DigitalOcean Spaces, etc.)
Requires vibe.d ~>0.10.2.
License
MIT
- ~main released 26 days ago
- kirillsaidov/minio-d
- MIT
- Authors:
- Dependencies:
- vibe-d
- Versions:
-
Show all 2 versions1.0.0 2026-Apr-04 ~main 2026-Apr-04 - Download Stats:
-
-
0 downloads today
-
0 downloads this week
-
4 downloads this month
-
4 downloads total
-
- Score:
- 0.1
- Short URL:
- minio-d.dub.pm