【依赖升级】AWS SDK for Java 1.x to 2.x

This commit is contained in:
puhui999 2025-02-06 16:05:56 +08:00
parent d83b7cd5b9
commit f141d64eb2
3 changed files with 133 additions and 70 deletions

View File

@ -68,7 +68,7 @@
<!-- 三方云服务相关 --> <!-- 三方云服务相关 -->
<commons-io.version>2.17.0</commons-io.version> <commons-io.version>2.17.0</commons-io.version>
<commons-compress.version>1.27.1</commons-compress.version> <commons-compress.version>1.27.1</commons-compress.version>
<aws-java-sdk-s3.version>1.12.777</aws-java-sdk-s3.version> <awssdk.version>2.30.14</awssdk.version>
<justauth.version>2.0.5</justauth.version> <justauth.version>2.0.5</justauth.version>
<jimureport.version>1.8.1</jimureport.version> <jimureport.version>1.8.1</jimureport.version>
<weixin-java.version>4.6.0</weixin-java.version> <weixin-java.version>4.6.0</weixin-java.version>
@ -91,6 +91,13 @@
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>${awssdk.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 业务组件 --> <!-- 业务组件 -->
<dependency> <dependency>
@ -538,13 +545,6 @@
<version>${jsoup.version}</version> <version>${jsoup.version}</version>
</dependency> </dependency>
<!-- 三方云服务相关 -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>${aws-java-sdk-s3.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.xingyuv</groupId> <groupId>com.xingyuv</groupId>
<artifactId>spring-boot-starter-justauth</artifactId> <!-- 社交登陆(例如说,个人微信、企业微信等等) --> <artifactId>spring-boot-starter-justauth</artifactId> <!-- 社交登陆(例如说,个人微信、企业微信等等) -->

View File

@ -115,9 +115,18 @@
<groupId>com.jcraft</groupId> <groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId> <!-- 文件客户端:解决 sftp 连接 --> <artifactId>jsch</artifactId> <!-- 文件客户端:解决 sftp 连接 -->
</dependency> </dependency>
<!-- 文件客户端解决阿里云、腾讯云、minio 等 S3 连接 -->
<dependency> <dependency>
<groupId>com.amazonaws</groupId> <groupId>software.amazon.awssdk</groupId>
<artifactId>aws-java-sdk-s3</artifactId><!-- 文件客户端解决阿里云、腾讯云、minio 等 S3 连接 --> <artifactId>s3</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>auth</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>regions</artifactId>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -4,65 +4,68 @@ import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil; import cn.hutool.http.HttpUtil;
import cn.iocoder.yudao.module.infra.framework.file.core.client.AbstractFileClient; import cn.iocoder.yudao.module.infra.framework.file.core.client.AbstractFileClient;
import com.amazonaws.HttpMethod; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials; import software.amazon.awssdk.core.sync.RequestBody;
import com.amazonaws.client.builder.AwsClientBuilder; import software.amazon.awssdk.regions.Region;
import com.amazonaws.services.s3.AmazonS3Client; import software.amazon.awssdk.services.s3.S3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder; import software.amazon.awssdk.services.s3.S3Configuration;
import com.amazonaws.services.s3.model.ObjectMetadata; import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
import com.amazonaws.services.s3.model.S3Object; import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest;
import java.io.ByteArrayInputStream; import java.net.URI;
import java.util.Date; import java.time.Duration;
import java.util.concurrent.TimeUnit;
/** /**
* 基于 S3 协议的文件客户端实现 MinIO阿里云腾讯云七牛云华为云等云服务 * 基于 S3 协议的文件客户端实现 MinIO阿里云腾讯云七牛云华为云等云服务
* <p>
* S3 协议的客户端采用亚马逊提供的 software.amazon.awssdk.s3
* *
* @author 芋道源码 * @author 芋道源码
*/ */
public class S3FileClient extends AbstractFileClient<S3FileClientConfig> { public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
private AmazonS3Client client; private S3Client client;
public S3FileClient(Long id, S3FileClientConfig config) { public S3FileClient(Long id, S3FileClientConfig config) {
super(id, config); super(id, config);
} }
@Override /**
protected void doInit() { * 动态创建 S3Presigner
// 补全 domain *
if (StrUtil.isEmpty(config.getDomain())) { * @param endpoint 节点地址
config.setDomain(buildDomain()); * @param accessKey 访问 Key
} * @param secretKey 访问 Secret
// 初始化客户端 * @return S3Presigner
client = (AmazonS3Client)AmazonS3ClientBuilder.standard() */
.withCredentials(buildCredentials()) private static S3Presigner createPresigner(String endpoint, String accessKey, String secretKey) {
.withEndpointConfiguration(buildEndpointConfiguration()) return S3Presigner.builder()
.credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey)))
.endpointOverride(URI.create(endpoint))
.build(); .build();
} }
/** /**
* 基于 config 秘钥构建 S3 客户端的认证信息 * 生成动态的预签名上传 URL
* *
* @return S3 客户端的认证信息 * @param bucket 存储 Bucket
* @param path 相对路径
* @param duration 过期时间
* @param endpoint 节点地址
* @param accessKey 访问 Key
* @param secretKey 访问 Secret
* @return 生成的上传 URL
*/ */
private AWSStaticCredentialsProvider buildCredentials() { public static String getPresignedUrl(String bucket, String path, Duration duration,
return new AWSStaticCredentialsProvider( String endpoint, String accessKey, String secretKey) {
new BasicAWSCredentials(config.getAccessKey(), config.getAccessSecret())); try (S3Presigner presigner = createPresigner(endpoint, accessKey, secretKey)) {
return presigner.presignPutObject(PutObjectPresignRequest.builder()
.signatureDuration(duration)
.putObjectRequest(b -> b.bucket(bucket).key(path))
.build()).url().toString();
} }
/**
* 构建 S3 客户端的 Endpoint 配置包括 regionendpoint
*
* @return S3 客户端的 EndpointConfiguration 配置
*/
private AwsClientBuilder.EndpointConfiguration buildEndpointConfiguration() {
return new AwsClientBuilder.EndpointConfiguration(config.getEndpoint(),
null); // 无需设置 region
} }
/** /**
@ -80,39 +83,90 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
} }
@Override @Override
public String upload(byte[] content, String path, String type) throws Exception { protected void doInit() {
// 元数据主要用于设置文件类型 // 补全 domain
ObjectMetadata objectMetadata = new ObjectMetadata(); if (StrUtil.isEmpty(config.getDomain())) {
objectMetadata.setContentType(type); config.setDomain(buildDomain());
objectMetadata.setContentLength(content.length); // 如果不设置会有 No content length specified for stream data 警告日志 }
// 执行上传 // 初始化 S3 客户端
client.putObject(config.getBucket(), client = S3Client.builder()
path, // 相对路径 .credentialsProvider(buildCredentials())
new ByteArrayInputStream(content), // 文件内容 .region(Region.of(config.getEndpoint())) // 这里随便填SDK 需要
objectMetadata); .endpointOverride(URI.create(buildEndpoint()))
.serviceConfiguration(S3Configuration.builder().pathStyleAccessEnabled(true).build()) // Path-style 访问
.build();
}
/**
* 基于 config 秘钥构建 S3 客户端的认证信息
*
* @return S3 客户端的认证信息
*/
private StaticCredentialsProvider buildCredentials() {
return StaticCredentialsProvider.create(
AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret()));
}
/**
* 节点地址补全协议头
*
* @return 节点地址
*/
private String buildEndpoint() {
// 如果已经是 http 或者 https则不进行拼接
if (HttpUtil.isHttp(config.getEndpoint()) || HttpUtil.isHttps(config.getEndpoint())) {
return config.getEndpoint();
}
return StrUtil.format("https://{}", config.getEndpoint());
}
@Override
public String upload(byte[] content, String path, String type) {
// 构造 PutObjectRequest
PutObjectRequest putRequest = PutObjectRequest.builder()
.bucket(config.getBucket())
.key(path)
.contentType(type)
.contentLength((long) content.length)
.build();
// 上传文件
client.putObject(putRequest, RequestBody.fromBytes(content));
// 拼接返回路径 // 拼接返回路径
return config.getDomain() + "/" + path; return config.getDomain() + "/" + path;
} }
@Override @Override
public void delete(String path) throws Exception { public void delete(String path) {
client.deleteObject(config.getBucket(), path); DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder()
.bucket(config.getBucket())
.key(path)
.build();
client.deleteObject(deleteRequest);
} }
@Override @Override
public byte[] getContent(String path) throws Exception { public byte[] getContent(String path) {
S3Object tempS3Object = client.getObject(config.getBucket(), path); GetObjectRequest getRequest = GetObjectRequest.builder()
return IoUtil.readBytes(tempS3Object.getObjectContent()); .bucket(config.getBucket())
.key(path)
.build();
return IoUtil.readBytes(client.getObject(getRequest));
} }
@Override @Override
public FilePresignedUrlRespDTO getPresignedObjectUrl(String path) throws Exception { public FilePresignedUrlRespDTO getPresignedObjectUrl(String path) {
// 设定过期时间为 10 分钟取值范围1 ~ 7 String presignedUrl = getPresignedUrl(
Date expiration = new Date(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(10)); config.getBucket(),
// 生成上传 URL path,
String uploadUrl = String.valueOf(client.generatePresignedUrl(config.getBucket(), path, expiration , HttpMethod.PUT)); Duration.ofMinutes(10),
return new FilePresignedUrlRespDTO(uploadUrl, config.getDomain() + "/" + path); config.getEndpoint(),
config.getAccessKey(),
config.getAccessSecret()
);
return new FilePresignedUrlRespDTO(presignedUrl, config.getDomain() + "/" + path);
} }
} }