Работа с AWS S3

В рамках данного руководства мы рассмотрим пример взаимодействия с файловым хранилищем Amazon S3 с помощью AWS SDK.

S3 – это крайне надежный и в то же время, крайне простой в работе сервис. В S3 мы работаем с так называемыми buckets (корзины), каждый их которых содержит файлы внутри. Эти файлы могут быть получены как через REST API, так и с помощью SOAP.

Перед началом работы по этому руководству необходимо выполнить следующие подготовительные шаги:

  1. Создать аккаунт на AWS Console
  2. Сгенерировать AWS Secret Key + Access Key с помощью сервиса IAM

После того как вы получите данные для подключения мы можем переходить к созданию проекта.

  1. Создайте новый gradle проект с помощью сайта Spring Inializr

2. Разархивируйте и откройте новый проект

3. Далее нам необходимо добавить зависимость AWS SDK в файл gradle.build

implementation group: 'com.amazonaws', name: 'aws-java-sdk', version: '1.12.52'

Теперь наш gradle.build файл имеет следующий вид:

plugins {
id 'org.springframework.boot' version '2.5.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}

group = 'net.proselyte'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
compileOnly {
extendsFrom annotationProcessor
}
}

repositories {
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'com.amazonaws:aws-java-sdk:1.12.52'
}

test {
useJUnitPlatform()
}

4. Создадим конфигурационный класс S3Config:

package net.proselyte.awss3.config;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class S3Config {

@Bean
public AmazonS3 s3client() {
AWSCredentials credentials = new BasicAWSCredentials(
"<AWS_ACCESS_KEY>",
"<AWS_SECRET_KEY>"
);

return AmazonS3ClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withRegion(Regions.US_EAST_1)
.build();
}
}

Здесь AWS_ACCESS_KEY и AWS_SCRECT_KEY – это данные, которые были сгенерированы в AWS IAM.

5. Создание бакета:
Реализуем класс S3Service, в котором у нас будет метод createBucket

package net.proselyte.awss3.service;

import com.amazonaws.services.s3.AmazonS3;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RequiredArgsConstructor
public class S3Service {
private final AmazonS3 s3client;

public void createBucket() {
String bucketName = "proselytetutorial";

if (s3client.doesBucketExistV2(bucketName)) {
log.info("Bucket {} already exists, use a different name", bucketName);
return;
}

s3client.createBucket(bucketName);
}
}

И тестовый класс, в котором попробуем выполнить данный метод:

package net.proselyte.awss3.service;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class S3ServiceTest {
@Autowired
private S3Service s3Service;

@Test
public void testCreateBucket() {
s3Service.createBucket();
}
}

После выполнения данного метода мы можем перейти в консоль AWS S3 и проверить:

6. Получение списка бакетов:

    public void listBuckets(){
        List<Bucket> buckets = s3client.listBuckets();
        log.info("buckets: {}", buckets);
    }

Также изменим тестовый класс:

package net.proselyte.awss3.service;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class S3ServiceTest {
@Autowired
private S3Service s3Service;

@Test
public void testCreateBucket() {
s3Service.createBucket();
}

@Test
public void testListBuckets(){
s3Service.listBuckets();
}
}

И выполним данный метод:
2021-08-23 11:16:22.833 INFO 75184 --- [ Test worker] net.proselyte.awss3.service.S3Service : buckets: [S3Bucket [name=proselytetutorial, creationDate=Mon Aug 23 11:02:28 EEST 2021, owner=S3Owner [name=proselytear,id=9772ab74173a02e9806225483854a8e66cc29b04b140889afa18b7f4ef85df8b]]

7. Загрузка файла

Для загрузки файла добавим новый файл в директорию src/main/resources/proselyte.txt и добавим новый метод:

    @SneakyThrows
    public void uploadFile() {
        String bucketName = "proselytetutorial";
        ClassLoader loader = S3Service.class.getClassLoader();
        File file = new File(loader.getResource("proselyte.txt").getFile());
        s3client.putObject(
                bucketName,
                "proselyte.txt",
                file);
    }

И изменим тестовый класс:

    @Test
    public void testUploadFile(){
        s3Service.uploadFile();
    }

После выполнения данного метода мы сможем увидеть файл в нашем бакете:

8. Получение файлов
Добавим новый метод в наш сервисный класс:

    public void listFiles() {
        String bucketName = "proselytetutorial";

        ObjectListing objects = s3client.listObjects(bucketName);
        for(S3ObjectSummary objectSummary : objects.getObjectSummaries()) {
            log.info("File name: {}", objectSummary.getKey());
        }
    }

И добавим новый метод в текстовый класс:

    @Test
    public void testListFiles(){
        s3Service.listFiles();
    }

При выполнении этого метода мы увидим в консоли:

2021-08-23 12:15:11.815 INFO 976 --- [ Test worker] n.proselyte.awss3.service.S3ServiceTest : Started S3ServiceTest in 5.44 seconds (JVM running for 7.582)
2021-08-23 12:15:13.473 INFO 976 --- [ Test worker] net.proselyte.awss3.service.S3Service : File name: proselyte.txt
BUILD SUCCESSFUL in 14s

9. Скачивание файла

Кроме простого получение деталей объекта, мы можем также и скачать файл:

    @SneakyThrows
    public void downloadFile() {
        String bucketName = "proselytetutorial";

        S3Object s3object = s3client.getObject(bucketName, "proselyte.txt");
        S3ObjectInputStream inputStream = s3object.getObjectContent();
        File file = new File("<PUT_DESIRED_PATH_HERE>");

        FileCopyUtils.copy(inputStream, new FileOutputStream(file));
    }

При вызове метода downloadFile мы увидим, что файл, путь к которому был указан, был заполнен данными из файла на S3.

10. Удаление файла

Для удаления файла нам необходимо передать имя бакета и ключ файла:

public void deleteFile() {
String bucketName = "proselytetutorial";
s3client.deleteObject(bucketName,"proselyte.txt");
}

После вызова метода мы можем увидеть, что файл был удален из бакета:

На этом мы заканчиваем обзор работы с AWS S3 средствами SDK.
Более детально с возможностями AWS SDK S3 вы можете ознакомиться в официальной документации
Ссылка на исходный код проекта