update 将 S3Client 改为 S3AsyncClient

This commit is contained in:
David Wei 2024-01-13 18:03:44 +08:00
parent 7338d7cdc8
commit 4b07b23aba
3 changed files with 42 additions and 55 deletions

View File

@ -30,24 +30,9 @@
<groupId>software.amazon.awssdk</groupId> <groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId> <artifactId>s3</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>software.amazon.awssdk</groupId> <groupId>software.amazon.awssdk</groupId>
<artifactId>kms</artifactId> <artifactId>netty-nio-client</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3control</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3-transfer-manager</artifactId>
</dependency>
<dependency>
<groupId>software.amazon.awssdk.crt</groupId>
<artifactId>aws-crt</artifactId>
<version>0.29.1</version>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -2,6 +2,7 @@ package org.dromara.common.oss.core;
import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import io.netty.handler.ssl.SslProvider;
import org.dromara.common.core.utils.DateUtils; import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.oss.constant.OssConstant; import org.dromara.common.oss.constant.OssConstant;
@ -12,7 +13,9 @@ import org.dromara.common.oss.exception.OssException;
import org.dromara.common.oss.properties.OssProperties; import org.dromara.common.oss.properties.OssProperties;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.core.async.AsyncRequestBody;
import software.amazon.awssdk.core.client.config.SdkAdvancedAsyncClientOption;
import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient;
import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.*; import software.amazon.awssdk.services.s3.*;
import software.amazon.awssdk.services.s3.model.*; import software.amazon.awssdk.services.s3.model.*;
@ -27,6 +30,7 @@ import java.io.InputStream;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.time.Duration; import java.time.Duration;
import java.util.concurrent.Executors;
/** /**
* S3-v2 存储协议 所有兼容S3协议的云厂商均支持 * S3-v2 存储协议 所有兼容S3协议的云厂商均支持
@ -40,7 +44,7 @@ public class OssClient {
private final OssProperties properties; private final OssProperties properties;
private final S3Client client; private final S3AsyncClient client;
private final S3Presigner presigner; private final S3Presigner presigner;
@ -51,23 +55,31 @@ public class OssClient {
StaticCredentialsProvider credentialsProvider = StaticCredentialsProvider.create( StaticCredentialsProvider credentialsProvider = StaticCredentialsProvider.create(
AwsBasicCredentials.create(properties.getAccessKey(), properties.getSecretKey())); AwsBasicCredentials.create(properties.getAccessKey(), properties.getSecretKey()));
S3Configuration.Builder config = S3Configuration.builder() S3AsyncClientBuilder client = S3AsyncClient.builder()
.chunkedEncodingEnabled(false); .httpClient(
if (!StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE)) { NettyNioAsyncHttpClient.builder()
// minio 使用https限制使用域名访问 需要此配置 站点填域名 .sslProvider(SslProvider.OPENSSL)
config.pathStyleAccessEnabled(true); .build()
} )
S3ClientBuilder client = S3Client.builder() .asyncConfiguration(
b -> b.advancedOption(SdkAdvancedAsyncClientOption
.FUTURE_COMPLETION_EXECUTOR,
Executors.newFixedThreadPool(10)
)
)
.credentialsProvider(credentialsProvider) .credentialsProvider(credentialsProvider)
.endpointOverride(URI.create(getEndpoint())) .endpointOverride(URI.create(getEndpoint()))
.region(Region.of(properties.getRegion())) .region(Region.of(properties.getRegion()));
.serviceConfiguration(config.build());
S3Presigner.Builder presigner = S3Presigner.builder() S3Presigner.Builder presigner = S3Presigner.builder()
.credentialsProvider(credentialsProvider) .credentialsProvider(credentialsProvider)
.endpointOverride(URI.create(getPresignerEndpoint())) .endpointOverride(URI.create(getPresignerEndpoint()))
.region(Region.of(properties.getRegion())) .region(Region.of(properties.getRegion()));
.serviceConfiguration(config.build());
if (!StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE)) {
// minio 使用https限制使用域名访问 需要此配置 站点填域名
client.forcePathStyle(true);
}
this.client = client.build(); this.client = client.build();
this.presigner = presigner.build(); this.presigner = presigner.build();
@ -87,7 +99,8 @@ public class OssClient {
try { try {
client.headBucket(HeadBucketRequest.builder() client.headBucket(HeadBucketRequest.builder()
.bucket(bucketName) .bucket(bucketName)
.build()); .build())
.get();
return; return;
} catch (Exception e) { } catch (Exception e) {
// 桶不存在捕获异常 // 桶不存在捕获异常
@ -103,8 +116,8 @@ public class OssClient {
.bucket(bucketName) .bucket(bucketName)
.policy(getPolicy(bucketName, accessPolicy.getPolicyType())) .policy(getPolicy(bucketName, accessPolicy.getPolicyType()))
.build(); .build();
client.createBucket(createBucketRequest); client.createBucket(createBucketRequest).get();
client.putBucketPolicy(putBucketPolicyRequest); client.putBucketPolicy(putBucketPolicyRequest).get();
} catch (Exception e) { } catch (Exception e) {
throw new OssException("创建Bucket失败, 请核对配置信息:[" + e.getMessage() + "]"); throw new OssException("创建Bucket失败, 请核对配置信息:[" + e.getMessage() + "]");
} }
@ -125,7 +138,11 @@ public class OssClient {
.contentType(contentType) .contentType(contentType)
.acl(getAccessPolicy().getObjectCannedACL()) // 设置上传对象的 Acl .acl(getAccessPolicy().getObjectCannedACL()) // 设置上传对象的 Acl
.build(); .build();
client.putObject(putObjectRequest, RequestBody.fromInputStream(inputStream, inputStream.available())); client.putObject(putObjectRequest, AsyncRequestBody.fromInputStream(
inputStream,
(long) inputStream.available(),
Executors.newFixedThreadPool(1)
)).get();
} catch (Exception e) { } catch (Exception e) {
throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]"); throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]");
} }
@ -139,7 +156,7 @@ public class OssClient {
.key(path) .key(path)
.acl(getAccessPolicy().getObjectCannedACL())// 设置上传对象的 Acl .acl(getAccessPolicy().getObjectCannedACL())// 设置上传对象的 Acl
.build(); .build();
client.putObject(putObjectRequest, RequestBody.fromFile(file)); client.putObject(putObjectRequest, AsyncRequestBody.fromFile(file)).get();
} catch (Exception e) { } catch (Exception e) {
throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]"); throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]");
} }
@ -153,7 +170,7 @@ public class OssClient {
.bucket(properties.getBucketName()) .bucket(properties.getBucketName())
.key(path) .key(path)
.build(); .build();
client.deleteObject(deleteObjectRequest); client.deleteObject(deleteObjectRequest).get();
} catch (Exception e) { } catch (Exception e) {
throw new OssException("删除文件失败,请检查配置信息:[" + e.getMessage() + "]"); throw new OssException("删除文件失败,请检查配置信息:[" + e.getMessage() + "]");
} }
@ -182,18 +199,7 @@ public class OssClient {
.bucket(properties.getBucketName()) .bucket(properties.getBucketName())
.key(path) .key(path)
.build(); .build();
return client.headObject(headObjectRequest).join();
return client.headObject(headObjectRequest);
}
public InputStream getObjectContent(String path) {
path = path.replace(getUrl() + "/", "");
GetObjectRequest getObjectRequest = GetObjectRequest.builder()
.bucket(properties.getBucketName())
.key(path)
.build();
return client.getObject(getObjectRequest);
} }
public String getEndpoint() { public String getEndpoint() {
@ -246,7 +252,6 @@ public class OssClient {
return path + suffix; return path + suffix;
} }
public String getConfigKey() { public String getConfigKey() {
return configKey; return configKey;
} }

View File

@ -1,8 +1,8 @@
package org.dromara.system.service.impl; package org.dromara.system.service.impl;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -114,18 +114,15 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
} }
@Override @Override
public void download(Long ossId, HttpServletResponse response) throws IOException { public void download(Long ossId, HttpServletResponse response) {
SysOssVo sysOss = SpringUtils.getAopProxy(this).getById(ossId); SysOssVo sysOss = SpringUtils.getAopProxy(this).getById(ossId);
if (ObjectUtil.isNull(sysOss)) { if (ObjectUtil.isNull(sysOss)) {
throw new ServiceException("文件数据不存在!"); throw new ServiceException("文件数据不存在!");
} }
FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName()); FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName());
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8"); response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");
OssClient storage = OssFactory.instance(sysOss.getService()); try {
try(InputStream inputStream = storage.getObjectContent(sysOss.getUrl())) { HttpUtil.download(this.matchingUrl(sysOss).getUrl(), response.getOutputStream(), true);
int available = inputStream.available();
IoUtil.copy(inputStream, response.getOutputStream(), available);
response.setContentLength(available);
} catch (Exception e) { } catch (Exception e) {
throw new ServiceException(e.getMessage()); throw new ServiceException(e.getMessage());
} }