!1219 【依赖升级】AWS SDK for Java 1.x to 2.x
Merge pull request !1219 from puhui999/develop
This commit is contained in:
commit
0885eb7c70
@ -71,7 +71,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.7.2.B</weixin-java.version>
|
<weixin-java.version>4.7.2.B</weixin-java.version>
|
||||||
@ -94,6 +94,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>
|
||||||
@ -551,13 +558,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> <!-- 社交登陆(例如说,个人微信、企业微信等等) -->
|
||||||
|
@ -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>
|
||||||
|
@ -4,29 +4,28 @@ 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.model.DeleteObjectRequest;
|
||||||
import com.amazonaws.services.s3.model.ObjectMetadata;
|
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
|
||||||
import com.amazonaws.services.s3.model.S3Object;
|
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);
|
||||||
@ -38,31 +37,82 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
|
|||||||
if (StrUtil.isEmpty(config.getDomain())) {
|
if (StrUtil.isEmpty(config.getDomain())) {
|
||||||
config.setDomain(buildDomain());
|
config.setDomain(buildDomain());
|
||||||
}
|
}
|
||||||
// 初始化客户端
|
// 初始化 S3 客户端
|
||||||
client = (AmazonS3Client)AmazonS3ClientBuilder.standard()
|
client = S3Client.builder()
|
||||||
.withCredentials(buildCredentials())
|
.credentialsProvider(buildCredentials())
|
||||||
.withEndpointConfiguration(buildEndpointConfiguration())
|
.region(Region.of("us-east-1")) // 必须填,但填什么都行,常见的值有 "us-east-1",不填会报错
|
||||||
|
.endpointOverride(URI.create(buildEndpoint()))
|
||||||
|
//.serviceConfiguration(S3Configuration.builder().pathStyleAccessEnabled(true).build()) // Path-style 访问
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(String path) {
|
||||||
|
DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder()
|
||||||
|
.bucket(config.getBucket())
|
||||||
|
.key(path)
|
||||||
|
.build();
|
||||||
|
client.deleteObject(deleteRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getContent(String path) {
|
||||||
|
GetObjectRequest getRequest = GetObjectRequest.builder()
|
||||||
|
.bucket(config.getBucket())
|
||||||
|
.key(path)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return IoUtil.readBytes(client.getObject(getRequest));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FilePresignedUrlRespDTO getPresignedObjectUrl(String path) {
|
||||||
|
return new FilePresignedUrlRespDTO(getPresignedUrl(path, Duration.ofMinutes(10)), config.getDomain() + "/" + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态创建 S3Presigner
|
||||||
|
*
|
||||||
|
* @return S3Presigner
|
||||||
|
*/
|
||||||
|
private S3Presigner createPresigner() {
|
||||||
|
return S3Presigner.builder()
|
||||||
|
.credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret())))
|
||||||
|
.region(Region.of("us-east-1")) // 必须填,但填什么都行,常见的值有 "us-east-1",不填会报错
|
||||||
|
.endpointOverride(URI.create(buildEndpoint()))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基于 config 秘钥,构建 S3 客户端的认证信息
|
* 生成动态的预签名上传 URL
|
||||||
*
|
*
|
||||||
* @return S3 客户端的认证信息
|
* @param path 相对路径
|
||||||
|
* @param duration 过期时间
|
||||||
|
* @return 生成的上传 URL
|
||||||
*/
|
*/
|
||||||
private AWSStaticCredentialsProvider buildCredentials() {
|
public String getPresignedUrl(String path, Duration duration) {
|
||||||
return new AWSStaticCredentialsProvider(
|
try (S3Presigner presigner = createPresigner()) {
|
||||||
new BasicAWSCredentials(config.getAccessKey(), config.getAccessSecret()));
|
return presigner.presignPutObject(PutObjectPresignRequest.builder()
|
||||||
}
|
.signatureDuration(duration)
|
||||||
|
.putObjectRequest(b -> b.bucket(config.getBucket()).key(path))
|
||||||
/**
|
.build()).url().toString();
|
||||||
* 构建 S3 客户端的 Endpoint 配置,包括 region、endpoint
|
}
|
||||||
*
|
|
||||||
* @return S3 客户端的 EndpointConfiguration 配置
|
|
||||||
*/
|
|
||||||
private AwsClientBuilder.EndpointConfiguration buildEndpointConfiguration() {
|
|
||||||
return new AwsClientBuilder.EndpointConfiguration(config.getEndpoint(),
|
|
||||||
null); // 无需设置 region
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -79,40 +129,27 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
|
|||||||
return StrUtil.format("https://{}.{}", config.getBucket(), config.getEndpoint());
|
return StrUtil.format("https://{}.{}", config.getBucket(), config.getEndpoint());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public String upload(byte[] content, String path, String type) throws Exception {
|
* 基于 config 秘钥,构建 S3 客户端的认证信息
|
||||||
// 元数据,主要用于设置文件类型
|
*
|
||||||
ObjectMetadata objectMetadata = new ObjectMetadata();
|
* @return S3 客户端的认证信息
|
||||||
objectMetadata.setContentType(type);
|
*/
|
||||||
objectMetadata.setContentLength(content.length); // 如果不设置,会有 “ No content length specified for stream data” 警告日志
|
private StaticCredentialsProvider buildCredentials() {
|
||||||
// 执行上传
|
return StaticCredentialsProvider.create(
|
||||||
client.putObject(config.getBucket(),
|
AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret()));
|
||||||
path, // 相对路径
|
|
||||||
new ByteArrayInputStream(content), // 文件内容
|
|
||||||
objectMetadata);
|
|
||||||
|
|
||||||
// 拼接返回路径
|
|
||||||
return config.getDomain() + "/" + path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
public void delete(String path) throws Exception {
|
* 节点地址补全协议头
|
||||||
client.deleteObject(config.getBucket(), path);
|
*
|
||||||
}
|
* @return 节点地址
|
||||||
|
*/
|
||||||
@Override
|
private String buildEndpoint() {
|
||||||
public byte[] getContent(String path) throws Exception {
|
// 如果已经是 http 或者 https,则不进行拼接
|
||||||
S3Object tempS3Object = client.getObject(config.getBucket(), path);
|
if (HttpUtil.isHttp(config.getEndpoint()) || HttpUtil.isHttps(config.getEndpoint())) {
|
||||||
return IoUtil.readBytes(tempS3Object.getObjectContent());
|
return config.getEndpoint();
|
||||||
}
|
}
|
||||||
|
return StrUtil.format("https://{}", config.getEndpoint());
|
||||||
@Override
|
|
||||||
public FilePresignedUrlRespDTO getPresignedObjectUrl(String path) throws Exception {
|
|
||||||
// 设定过期时间为 10 分钟。取值范围:1 秒 ~ 7 天
|
|
||||||
Date expiration = new Date(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(10));
|
|
||||||
// 生成上传 URL
|
|
||||||
String uploadUrl = String.valueOf(client.generatePresignedUrl(config.getBucket(), path, expiration , HttpMethod.PUT));
|
|
||||||
return new FilePresignedUrlRespDTO(uploadUrl, config.getDomain() + "/" + path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user