Работа с S3 и облачными хранилищами в Java с помощью AWS SDK и MinIO
Облачные объектные хранилища, совместимые с протоколом Amazon S3 (Simple Storage Service), стали стандартом де-факто для хранения неструктурированных данных: изображений, видео, логов, резервных копий и артефактов сборки. В Java основным инструментом для взаимодействия с такими хранилищами является AWS SDK for Java (модуль S3). Однако, для локальной разработки, тестирования или работы с self-hosted решениями часто используется MinIO — высокопроизводительное S3-совместимое хранилище с собственным Java-клиентом. В этой статье мы рассмотрим оба подхода.
1. Подготовка и подключение зависимостей
Для начала добавьте зависимости в ваш pom.xml (Maven):
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.30.0</version>
</dependency>
<!-- Для MinIO (альтернатива AWS SDK) -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.17</version>
</dependency>
2. Создание S3-клиента
Рассмотрим два способа создания клиента: для Amazon S3 (AWS) и для MinIO (локальное/кастомное хранилище).
2.1. Клиент для Amazon S3 (AWS SDK)
Используйте статический билдер, указав регион и способ аутентификации (например, через переменные окружения или профиль IAM).
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(); // Использует цепочку провайдеров по умолчанию
}
}
2.2. Клиент для MinIO
MinIO требует явного указания endpoint, access key и 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. Основные операции с бакетами и объектами
Независимо от выбранного клиента, логика работы с S3 универсальна. Рассмотрим ключевые сценарии.
3.1. Проверка существования и создание бакета
// AWS SDK
public boolean bucketExists(S3Client s3, String bucketName) {
return s3.headBucket(HeadBucketRequest.builder()
.bucket(bucketName)
.build())
.sdkHttpResponse().isSuccessful();
}
// MinIO SDK
public boolean bucketExists(MinioClient minio, String bucketName) {
return minio.bucketExists(BucketExistsArgs.builder()
.bucket(bucketName)
.build());
}
// Создание бакета (AWS)
s3.createBucket(CreateBucketRequest.builder()
.bucket("my-unique-bucket-123")
.createBucketConfiguration(
CreateBucketConfiguration.builder()
.locationConstraint("eu-central-1")
.build())
.build());
// Создание бакета (MinIO)
minio.makeBucket(MakeBucketArgs.builder()
.bucket("my-local-bucket")
.build());
3.2. Загрузка файла (Upload)
Загрузка файла из локального пути или из потока данных.
// AWS SDK - из файла
s3.putObject(PutObjectRequest.builder()
.bucket("my-bucket")
.key("uploads/report.pdf")
.build(),
Paths.get("/local/path/report.pdf"));
// MinIO SDK - из InputStream
try (InputStream is = new FileInputStream("/local/path/photo.jpg")) {
minio.putObject(PutObjectArgs.builder()
.bucket("my-bucket")
.object("images/photo.jpg")
.stream(is, file.length(), -1) // -1 для неизвестного размера
.contentType("image/jpeg")
.build());
}
3.3. Скачивание файла (Download)
Получение объекта и сохранение его на диск или обработка в памяти.
// AWS SDK - в файл
s3.getObject(GetObjectRequest.builder()
.bucket("my-bucket")
.key("data/config.json"),
Paths.get("/tmp/config.json"));
// MinIO SDK - в OutputStream
try (OutputStream out = new FileOutputStream("/tmp/backup.sql")) {
minio.getObject(GetObjectArgs.builder()
.bucket("my-bucket")
.object("back