Working with S3 and Cloud Storage in Java using AWS SDK and MinIO
Cloud object storage compatible with the Amazon S3 (Simple Storage Service) protocol has become the de facto standard for storing unstructured data: images, videos, logs, backups, and build artifacts. In Java, the primary tool for interacting with such storage is the AWS SDK for Java (S3 module). However, for local development, testing, or working with self-hosted solutions, MinIO is often used — a high-performance S3-compatible storage with its own Java client. In this article, we will cover both approaches.
1. Preparation and Adding Dependencies
First, add the dependencies to your pom.xml (Maven):
<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3</artifactId> <version>2.30.0</version></dependency>
<!-- For MinIO (alternative to AWS SDK) --><dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>8.5.17</version></dependency>2. Creating an S3 Client
Let's look at two ways to create a client: for Amazon S3 (AWS) and for MinIO (local/custom storage).
2.1. Client for Amazon S3 (AWS SDK)
Use the static builder, specifying the region and authentication method (e.g., via environment variables or an IAM profile).
import software.amazon.awssdk.regions.Region;import software.amazon.awssdk.services.s3.S3Client;
public class AwsS3Example { public static S3Client createAwsS3Client() { return S3Client.builder() .region(Region.EU_CENTRAL_1) // Frankfurt .build(); // Uses the default provider chain }}2.2. Client for MinIO
MinIO requires explicitly specifying the endpoint, access key, and secret key.
import io.minio.MinioClient;
public class MinioExample { public static MinioClient createMinioClient() { return MinioClient.builder() .endpoint("http://localhost:9000") .credentials("minioadmin", "minioadmin") .build(); }}3. Basic Operations with Buckets and Objects
Regardless of the chosen client, the logic for working with S3 is universal. Let's look at key scenarios.
3.1. Checking Bucket Existence and Creating a Bucket
// AWS SDKpublic boolean bucketExists(S3Client s3, String bucketName) { return s3.headBucket(HeadBucketRequest.builder() .bucket(bucketName) .build()) .sdkHttpResponse().isSuccessful();}
// MinIO SDKpublic boolean bucketExists(MinioClient minio, String bucketName) { return minio.bucketExists(BucketExistsArgs.builder() .bucket(bucketName) .build());}
// Creating a bucket (AWS)s3.createBucket(CreateBucketRequest.builder() .bucket("my-unique-bucket-123") .createBucketConfiguration( CreateBucketConfiguration.builder() .locationConstraint("eu-central-1") .build()) .build());
// Creating a bucket (MinIO)minio.makeBucket(MakeBucketArgs.builder() .bucket("my-local-bucket") .build());3.2. Uploading a File (Upload)
Uploading a file from a local path or from a data stream.
// AWS SDK - from files3.putObject(PutObjectRequest.builder() .bucket("my-bucket") .key("uploads/report.pdf") .build(), Paths.get("/local/path/report.pdf"));
// MinIO SDK - from InputStreamtry (InputStream is = new FileInputStream("/local/path/photo.jpg")) { minio.putObject(PutObjectArgs.builder()