|
@@ -14,14 +14,16 @@ 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.async.AsyncRequestBody;
|
|
|
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
|
|
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
|
|
|
-import software.amazon.awssdk.core.async.BlockingInputStreamAsyncRequestBody;
|
|
|
|
|
import software.amazon.awssdk.core.async.ResponsePublisher;
|
|
import software.amazon.awssdk.core.async.ResponsePublisher;
|
|
|
import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient;
|
|
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.S3AsyncClient;
|
|
import software.amazon.awssdk.services.s3.S3AsyncClient;
|
|
|
import software.amazon.awssdk.services.s3.S3Configuration;
|
|
import software.amazon.awssdk.services.s3.S3Configuration;
|
|
|
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
|
|
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
|
|
|
|
|
+import software.amazon.awssdk.services.s3.model.PutObjectRequest;
|
|
|
|
|
+import software.amazon.awssdk.services.s3.model.PutObjectResponse;
|
|
|
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
|
|
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
|
|
|
import software.amazon.awssdk.transfer.s3.S3TransferManager;
|
|
import software.amazon.awssdk.transfer.s3.S3TransferManager;
|
|
|
import software.amazon.awssdk.transfer.s3.model.*;
|
|
import software.amazon.awssdk.transfer.s3.model.*;
|
|
@@ -188,38 +190,23 @@ public class OssClient {
|
|
|
inputStream = new ByteArrayInputStream(IoUtil.readBytes(inputStream));
|
|
inputStream = new ByteArrayInputStream(IoUtil.readBytes(inputStream));
|
|
|
}
|
|
}
|
|
|
try {
|
|
try {
|
|
|
- // 创建异步请求体(length如果为空会报错)
|
|
|
|
|
- BlockingInputStreamAsyncRequestBody body = BlockingInputStreamAsyncRequestBody.builder()
|
|
|
|
|
- .contentLength(length)
|
|
|
|
|
- .subscribeTimeout(Duration.ofSeconds(120))
|
|
|
|
|
|
|
+ // 读取所有字节数据
|
|
|
|
|
+ byte[] bytes = IoUtil.readBytes(inputStream);
|
|
|
|
|
+
|
|
|
|
|
+ // 直接使用 S3AsyncClient.putObject 上传,避免 BlockingInputStreamAsyncRequestBody
|
|
|
|
|
+ // 在 Undertow 单线程模型下的 doBlockingWrite 120秒超时问题
|
|
|
|
|
+ PutObjectRequest putObjectRequest = PutObjectRequest.builder()
|
|
|
|
|
+ .bucket(properties.getBucketName())
|
|
|
|
|
+ .key(key)
|
|
|
|
|
+ .contentType(contentType)
|
|
|
.build();
|
|
.build();
|
|
|
|
|
|
|
|
- // 使用 transferManager 进行上传
|
|
|
|
|
- Upload upload = transferManager.upload(
|
|
|
|
|
- x -> {
|
|
|
|
|
- x.requestBody(body).putObjectRequest(
|
|
|
|
|
- y -> y.bucket(properties.getBucketName())
|
|
|
|
|
- .key(key)
|
|
|
|
|
- .contentType(contentType)
|
|
|
|
|
- // 用于设置对象的访问控制列表(ACL)。不同云厂商对ACL的支持和实现方式有所不同,
|
|
|
|
|
- // 因此根据具体的云服务提供商,你可能需要进行不同的配置(自行开启,阿里云有acl权限配置,腾讯云没有acl权限配置)
|
|
|
|
|
- //.acl(getAccessPolicy().getObjectCannedACL())
|
|
|
|
|
- .build()
|
|
|
|
|
- );
|
|
|
|
|
- if (log.isDebugEnabled()) {
|
|
|
|
|
- x.addTransferListener(LoggingTransferListener.create());
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ PutObjectResponse response = client.putObject(
|
|
|
|
|
+ putObjectRequest,
|
|
|
|
|
+ AsyncRequestBody.fromBytes(bytes)
|
|
|
|
|
+ ).join();
|
|
|
|
|
|
|
|
- // 将输入流写入请求体
|
|
|
|
|
- body.writeInputStream(inputStream);
|
|
|
|
|
-
|
|
|
|
|
- // 等待文件上传操作完成
|
|
|
|
|
- CompletedUpload uploadResult = upload.completionFuture().join();
|
|
|
|
|
- String eTag = uploadResult.response().eTag();
|
|
|
|
|
-
|
|
|
|
|
- // 提取上传结果中的 ETag,并构建一个自定义的 UploadResult 对象
|
|
|
|
|
|
|
+ String eTag = response.eTag();
|
|
|
return UploadResult.builder().url(getUrl() + StringUtils.SLASH + key).filename(key).eTag(eTag).build();
|
|
return UploadResult.builder().url(getUrl() + StringUtils.SLASH + key).filename(key).eTag(eTag).build();
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]");
|
|
throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]");
|