You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AWS SDK for Java对接Minio时S3AsyncClient与S3TransferManager区域问题

问题分析与解决:Spring Boot对接Minio时AWS SDK区域加载失败

错误日志

Unable to load region from software.amazon.awssdk.regions.providers.SystemSettingsRegionProvider@ee630de:Unable to load region from system settings. Region must be specified either via environment variable (AWS_REGION) or  system property (aws.region).
s.a.a.r.p.AwsRegionProviderChain : Unable to load region from software.amazon.awssdk.regions.providers.AwsProfileRegionProvider@22590efb:No region provided in profile: default
s.a.a.r.p.AwsRegionProviderChain: Unable to load region from software.amazon.awssdk.regions.providers.InstanceProfileRegionProvider@6c5be4c6:Unable to contact EC2 metadata service.

用户配置与代码

application.properties

minio.access.url=http://localhost:9000
minio.access.name=minioadmin
minio.access.secret=minioadmin
aws.region=us-east-1

Minio配置类

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3AsyncClient;

import java.net.URI;

import static software.amazon.awssdk.transfer.s3.SizeConstant.MB;

@Configuration
public class MinioConfig {

    @Value("${minio.access.url}")
    private String minioUrl;

    @Value("${minio.access.name}")
    private String accessKey;

    @Value("${minio.access.secret}")
    private String accessSecret;


    @Bean
    public S3AsyncClient generateMinioClient(){
        return S3AsyncClient.crtBuilder()
                .endpointOverride(URI.create(minioUrl))
                .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, accessSecret)))
                .region(Region.EU_CENTRAL_2)
                .targetThroughputInGbps(20.0)
                .minimumPartSizeInBytes(8 * MB)
                .build();

    }
}

服务类代码

import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.CompletedFileUpload;
import software.amazon.awssdk.transfer.s3.model.UploadFileRequest;
import software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener;

import java.net.URI;
import java.nio.file.Paths;
import java.util.concurrent.CompletableFuture;

@Service
@AllArgsConstructor
public class FileStorageService {
    private final StorageSystem storageSystem;

    public CompletableFuture<CompletedFileUpload> uploadFile(String username, String fileName, URI fileUri) {
        try (S3TransferManager transferManager = S3TransferManager.create()) {
            UploadFileRequest request = UploadFileRequest.builder()
                    .putObjectRequest(req -> req.bucket(username).key("key"))
                    .addTransferListener(LoggingTransferListener.create())
                    .source(Paths.get(fileName))
                    .build();

            return transferManager.uploadFile(request).completionFuture();
        }
    }
}

问题原因

核心问题是你自定义的S3AsyncClient没有被S3TransferManager使用。当前代码中S3TransferManager.create()会默认创建全新的S3客户端实例,这个实例会走AWS SDK默认的区域提供者链(系统环境变量、AWS配置文件、EC2元数据服务)加载区域,而本地Minio环境下这些渠道都没有配置区域,因此抛出加载失败错误。

另外,application.properties中设置的aws.region不会生效,因为默认创建的S3客户端不会读取Spring配置属性,且自定义客户端并未传递给S3TransferManager。

解决方案

1. 修改服务类,注入自定义的S3AsyncClient

将FileStorageService中的StorageSystem替换为自定义的S3AsyncClient,并使用该客户端创建S3TransferManager:

import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.CompletedFileUpload;
import software.amazon.awssdk.transfer.s3.model.UploadFileRequest;
import software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener;

import java.nio.file.Paths;
import java.util.concurrent.CompletableFuture;

@Service
@AllArgsConstructor
public class FileStorageService {
    private final S3AsyncClient s3AsyncClient;

    public CompletableFuture<CompletedFileUpload> uploadFile(String username, String fileName) {
        try (S3TransferManager transferManager = S3TransferManager.builder()
                .s3Client(s3AsyncClient)
                .build()) {
            UploadFileRequest request = UploadFileRequest.builder()
                    .putObjectRequest(req -> req.bucket(username).key("key"))
                    .addTransferListener(LoggingTransferListener.create())
                    .source(Paths.get(fileName))
                    .build();

            return transferManager.uploadFile(request).completionFuture();
        }
    }
}

(注:移除了未使用的URI参数,可根据实际需求调整)

2. 统一Region配置

Minio对Region校验宽松,可选择:

  • 使用Region.of("us-east-1")(Minio默认区域),与application.properties配置保持一致
  • 继续使用Region.EU_CENTRAL_2(当前代码配置),只要是AWS SDK认可的Region字符串即可,Minio会正常处理。

无需额外配置,只要保证S3TransferManager使用自定义的S3AsyncClient实例,区域问题即可解决。

补充说明

  • application.properties中的aws.region对自定义客户端无效,因为自定义客户端的Region是通过.region()方法显式指定的,优先级高于系统配置。
  • Region.of("us-east-1")是正确用法,只要是AWS SDK认可的Region字符串都可,Minio仅将其作为标识使用,不做严格校验。

内容的提问来源于stack exchange,提问作者wallhack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 13:04:50