Как подключить S3 для хранения файловS3-совместимое хранилище (AWS S3, MinIO, Yandex Object Storage и т.п.) — удобный способ хранить файлы вне приложения. Подключим его к Spring Boot и реализуем минимальный upload/download.
Зависимости
software.amazon.awssdk
s3
2.25.60
org.springframework.boot
spring-boot-starter-web
ИЛИ
implementation 'software.amazon.awssdk:s3:2.25.60'
implementation 'org.springframework.boot:spring-boot-starter-web'
Конфигурация (application.yml)s3:
region: eu-central-1
accessKey: minioadmin
secretKey: minioadmin
bucket: demo-bucket
spring:
servlet:
multipart:
max-file-size: 20MB
max-request-size: 20MB
Бины клиента S3@Configuration
public class S3Config {
@Bean
public S3Client s3Client(S3Props props) {
var builder = S3Client.builder()
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create(props.accessKey(), props.secretKey())))
.region(Region.of(props.region()))
.httpClientBuilder(UrlConnectionHttpClient.builder());
if (props.endpoint() != null && !props.endpoint().isBlank()) {
builder = builder
.endpointOverride(java.net.URI.create(props.endpoint()))
.serviceConfiguration(S3Configuration.builder()
.pathStyleAccessEnabled(props.pathStyleAccess())
.build());
}
return builder.build();
}
@Bean
public S3Props s3Props(org.springframework.core.env.Environment env) {
return new S3Props(
env.getProperty("s3.endpoint"),
env.getProperty("s3.region", "eu-central-1"),
env.getProperty("s3.accessKey"),
env.getProperty("s3.secretKey"),
env.getProperty("s3.bucket", "demo-bucket"),
Boolean.parseBoolean(env.getProperty("s3.pathStyleAccess", "true"))
);
}
public record S3Props(String endpoint, String region, String accessKey,
String secretKey, String bucket, boolean pathStyleAccess) {}
}
Сервис для загрузки/скачивания@Service
@RequiredArgsConstructor
public class S3StorageService {
private final S3Client s3;
private final S3Config.S3Props props;
public String upload(String originalName, String contentType, byte[] bytes) {
String key = UUID.randomUUID() + "_" + originalName;
s3.putObject(PutObjectRequest.builder()
.bucket(props.bucket())
.key(key)
.contentType(contentType)
.build(),
RequestBody.fromBytes(bytes));
return key;
}
public byte[] download(String key) {
GetObjectResponse[] meta = new GetObjectResponse[1];
try (var resp = s3.getObject(GetObjectRequest.builder()
.bucket(props.bucket()).key(key).build())) {
meta[0] = resp.response();
return resp.readAllBytes();
} catch (Exception e) {
throw NoSuchKeyException.builder().message("Object not found: " + key).build();
}
}
public void createBucketIfMissing() {
var bucket = props.bucket();
var exists = s3.listBuckets().buckets().stream().anyMatch(b -> b.name().equals(bucket));
if (!exists) s3.createBucket(CreateBucketRequest.builder().bucket(bucket).build());
}
}
Как вы храните пользовательские файлы в продакшене? Библиотека джависта
#буст
2.21K viewsedited 09:17