Commit f141d64eb2bd755a44564157d3c5254506230d11

Authored by puhui999
1 parent d83b7cd5

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

yudao-dependencies/pom.xml
... ... @@ -68,7 +68,7 @@
68 68 <!-- 三方云服务相关 -->
69 69 <commons-io.version>2.17.0</commons-io.version>
70 70 <commons-compress.version>1.27.1</commons-compress.version>
71   - <aws-java-sdk-s3.version>1.12.777</aws-java-sdk-s3.version>
  71 + <awssdk.version>2.30.14</awssdk.version>
72 72 <justauth.version>2.0.5</justauth.version>
73 73 <jimureport.version>1.8.1</jimureport.version>
74 74 <weixin-java.version>4.6.0</weixin-java.version>
... ... @@ -91,6 +91,13 @@
91 91 <type>pom</type>
92 92 <scope>import</scope>
93 93 </dependency>
  94 + <dependency>
  95 + <groupId>software.amazon.awssdk</groupId>
  96 + <artifactId>bom</artifactId>
  97 + <version>${awssdk.version}</version>
  98 + <type>pom</type>
  99 + <scope>import</scope>
  100 + </dependency>
94 101  
95 102 <!-- 业务组件 -->
96 103 <dependency>
... ... @@ -538,13 +545,6 @@
538 545 <version>${jsoup.version}</version>
539 546 </dependency>
540 547  
541   - <!-- 三方云服务相关 -->
542   - <dependency>
543   - <groupId>com.amazonaws</groupId>
544   - <artifactId>aws-java-sdk-s3</artifactId>
545   - <version>${aws-java-sdk-s3.version}</version>
546   - </dependency>
547   -
548 548 <dependency>
549 549 <groupId>com.xingyuv</groupId>
550 550 <artifactId>spring-boot-starter-justauth</artifactId> <!-- 社交登陆(例如说,个人微信、企业微信等等) -->
... ...
yudao-module-infra/yudao-module-infra-biz/pom.xml
... ... @@ -115,9 +115,18 @@
115 115 <groupId>com.jcraft</groupId>
116 116 <artifactId>jsch</artifactId> <!-- 文件客户端:解决 sftp 连接 -->
117 117 </dependency>
  118 + <!-- 文件客户端:解决阿里云、腾讯云、minio 等 S3 连接 -->
118 119 <dependency>
119   - <groupId>com.amazonaws</groupId>
120   - <artifactId>aws-java-sdk-s3</artifactId><!-- 文件客户端:解决阿里云、腾讯云、minio 等 S3 连接 -->
  120 + <groupId>software.amazon.awssdk</groupId>
  121 + <artifactId>s3</artifactId>
  122 + </dependency>
  123 + <dependency>
  124 + <groupId>software.amazon.awssdk</groupId>
  125 + <artifactId>auth</artifactId>
  126 + </dependency>
  127 + <dependency>
  128 + <groupId>software.amazon.awssdk</groupId>
  129 + <artifactId>regions</artifactId>
121 130 </dependency>
122 131  
123 132 <dependency>
... ...
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java
... ... @@ -4,65 +4,68 @@ import cn.hutool.core.io.IoUtil;
4 4 import cn.hutool.core.util.StrUtil;
5 5 import cn.hutool.http.HttpUtil;
6 6 import cn.iocoder.yudao.module.infra.framework.file.core.client.AbstractFileClient;
7   -import com.amazonaws.HttpMethod;
8   -import com.amazonaws.auth.AWSStaticCredentialsProvider;
9   -import com.amazonaws.auth.BasicAWSCredentials;
10   -import com.amazonaws.client.builder.AwsClientBuilder;
11   -import com.amazonaws.services.s3.AmazonS3Client;
12   -import com.amazonaws.services.s3.AmazonS3ClientBuilder;
13   -import com.amazonaws.services.s3.model.ObjectMetadata;
14   -import com.amazonaws.services.s3.model.S3Object;
15   -
16   -import java.io.ByteArrayInputStream;
17   -import java.util.Date;
18   -import java.util.concurrent.TimeUnit;
  7 +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
  8 +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
  9 +import software.amazon.awssdk.core.sync.RequestBody;
  10 +import software.amazon.awssdk.regions.Region;
  11 +import software.amazon.awssdk.services.s3.S3Client;
  12 +import software.amazon.awssdk.services.s3.S3Configuration;
  13 +import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
  14 +import software.amazon.awssdk.services.s3.model.GetObjectRequest;
  15 +import software.amazon.awssdk.services.s3.model.PutObjectRequest;
  16 +import software.amazon.awssdk.services.s3.presigner.S3Presigner;
  17 +import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest;
  18 +
  19 +import java.net.URI;
  20 +import java.time.Duration;
19 21  
20 22 /**
21 23 * 基于 S3 协议的文件客户端,实现 MinIO、阿里云、腾讯云、七牛云、华为云等云服务
22   - * <p>
23   - * S3 协议的客户端,采用亚马逊提供的 software.amazon.awssdk.s3 库
24 24 *
25 25 * @author 芋道源码
26 26 */
27 27 public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
28 28  
29   - private AmazonS3Client client;
  29 + private S3Client client;
30 30  
31 31 public S3FileClient(Long id, S3FileClientConfig config) {
32 32 super(id, config);
33 33 }
34 34  
35   - @Override
36   - protected void doInit() {
37   - // 补全 domain
38   - if (StrUtil.isEmpty(config.getDomain())) {
39   - config.setDomain(buildDomain());
40   - }
41   - // 初始化客户端
42   - client = (AmazonS3Client)AmazonS3ClientBuilder.standard()
43   - .withCredentials(buildCredentials())
44   - .withEndpointConfiguration(buildEndpointConfiguration())
45   - .build();
46   - }
47   -
48 35 /**
49   - * 基于 config 秘钥,构建 S3 客户端的认证信息
  36 + * 动态创建 S3Presigner
50 37 *
51   - * @return S3 客户端的认证信息
  38 + * @param endpoint 节点地址
  39 + * @param accessKey 访问 Key
  40 + * @param secretKey 访问 Secret
  41 + * @return S3Presigner
52 42 */
53   - private AWSStaticCredentialsProvider buildCredentials() {
54   - return new AWSStaticCredentialsProvider(
55   - new BasicAWSCredentials(config.getAccessKey(), config.getAccessSecret()));
  43 + private static S3Presigner createPresigner(String endpoint, String accessKey, String secretKey) {
  44 + return S3Presigner.builder()
  45 + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey)))
  46 + .endpointOverride(URI.create(endpoint))
  47 + .build();
56 48 }
57 49  
58 50 /**
59   - * 构建 S3 客户端的 Endpoint 配置,包括 region、endpoint
  51 + * 生成动态的预签名上传 URL
60 52 *
61   - * @return S3 客户端的 EndpointConfiguration 配置
  53 + * @param bucket 存储 Bucket
  54 + * @param path 相对路径
  55 + * @param duration 过期时间
  56 + * @param endpoint 节点地址
  57 + * @param accessKey 访问 Key
  58 + * @param secretKey 访问 Secret
  59 + * @return 生成的上传 URL
62 60 */
63   - private AwsClientBuilder.EndpointConfiguration buildEndpointConfiguration() {
64   - return new AwsClientBuilder.EndpointConfiguration(config.getEndpoint(),
65   - null); // 无需设置 region
  61 + public static String getPresignedUrl(String bucket, String path, Duration duration,
  62 + String endpoint, String accessKey, String secretKey) {
  63 + try (S3Presigner presigner = createPresigner(endpoint, accessKey, secretKey)) {
  64 + return presigner.presignPutObject(PutObjectPresignRequest.builder()
  65 + .signatureDuration(duration)
  66 + .putObjectRequest(b -> b.bucket(bucket).key(path))
  67 + .build()).url().toString();
  68 + }
66 69 }
67 70  
68 71 /**
... ... @@ -80,39 +83,90 @@ public class S3FileClient extends AbstractFileClient&lt;S3FileClientConfig&gt; {
80 83 }
81 84  
82 85 @Override
83   - public String upload(byte[] content, String path, String type) throws Exception {
84   - // 元数据,主要用于设置文件类型
85   - ObjectMetadata objectMetadata = new ObjectMetadata();
86   - objectMetadata.setContentType(type);
87   - objectMetadata.setContentLength(content.length); // 如果不设置,会有 “ No content length specified for stream data” 警告日志
88   - // 执行上传
89   - client.putObject(config.getBucket(),
90   - path, // 相对路径
91   - new ByteArrayInputStream(content), // 文件内容
92   - objectMetadata);
  86 + protected void doInit() {
  87 + // 补全 domain
  88 + if (StrUtil.isEmpty(config.getDomain())) {
  89 + config.setDomain(buildDomain());
  90 + }
  91 + // 初始化 S3 客户端
  92 + client = S3Client.builder()
  93 + .credentialsProvider(buildCredentials())
  94 + .region(Region.of(config.getEndpoint())) // 这里随便填,SDK 需要
  95 + .endpointOverride(URI.create(buildEndpoint()))
  96 + .serviceConfiguration(S3Configuration.builder().pathStyleAccessEnabled(true).build()) // Path-style 访问
  97 + .build();
  98 + }
  99 +
  100 + /**
  101 + * 基于 config 秘钥,构建 S3 客户端的认证信息
  102 + *
  103 + * @return S3 客户端的认证信息
  104 + */
  105 + private StaticCredentialsProvider buildCredentials() {
  106 + return StaticCredentialsProvider.create(
  107 + AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret()));
  108 + }
  109 +
  110 + /**
  111 + * 节点地址补全协议头
  112 + *
  113 + * @return 节点地址
  114 + */
  115 + private String buildEndpoint() {
  116 + // 如果已经是 http 或者 https,则不进行拼接
  117 + if (HttpUtil.isHttp(config.getEndpoint()) || HttpUtil.isHttps(config.getEndpoint())) {
  118 + return config.getEndpoint();
  119 + }
  120 + return StrUtil.format("https://{}", config.getEndpoint());
  121 + }
  122 +
  123 + @Override
  124 + public String upload(byte[] content, String path, String type) {
  125 + // 构造 PutObjectRequest
  126 + PutObjectRequest putRequest = PutObjectRequest.builder()
  127 + .bucket(config.getBucket())
  128 + .key(path)
  129 + .contentType(type)
  130 + .contentLength((long) content.length)
  131 + .build();
93 132  
  133 + // 上传文件
  134 + client.putObject(putRequest, RequestBody.fromBytes(content));
94 135 // 拼接返回路径
95 136 return config.getDomain() + "/" + path;
96 137 }
97 138  
98 139 @Override
99   - public void delete(String path) throws Exception {
100   - client.deleteObject(config.getBucket(), path);
  140 + public void delete(String path) {
  141 + DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder()
  142 + .bucket(config.getBucket())
  143 + .key(path)
  144 + .build();
  145 + client.deleteObject(deleteRequest);
101 146 }
102 147  
103 148 @Override
104   - public byte[] getContent(String path) throws Exception {
105   - S3Object tempS3Object = client.getObject(config.getBucket(), path);
106   - return IoUtil.readBytes(tempS3Object.getObjectContent());
  149 + public byte[] getContent(String path) {
  150 + GetObjectRequest getRequest = GetObjectRequest.builder()
  151 + .bucket(config.getBucket())
  152 + .key(path)
  153 + .build();
  154 +
  155 + return IoUtil.readBytes(client.getObject(getRequest));
107 156 }
108 157  
109 158 @Override
110   - public FilePresignedUrlRespDTO getPresignedObjectUrl(String path) throws Exception {
111   - // 设定过期时间为 10 分钟。取值范围:1 秒 ~ 7 天
112   - Date expiration = new Date(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(10));
113   - // 生成上传 URL
114   - String uploadUrl = String.valueOf(client.generatePresignedUrl(config.getBucket(), path, expiration , HttpMethod.PUT));
115   - return new FilePresignedUrlRespDTO(uploadUrl, config.getDomain() + "/" + path);
  159 + public FilePresignedUrlRespDTO getPresignedObjectUrl(String path) {
  160 + String presignedUrl = getPresignedUrl(
  161 + config.getBucket(),
  162 + path,
  163 + Duration.ofMinutes(10),
  164 + config.getEndpoint(),
  165 + config.getAccessKey(),
  166 + config.getAccessSecret()
  167 + );
  168 +
  169 + return new FilePresignedUrlRespDTO(presignedUrl, config.getDomain() + "/" + path);
116 170 }
117 171  
118 172 }
... ...