Commit cf40cce552590995096e1b081cce34fe7e23421d
1 parent
f141d64e
【代码优化】S3FileClient
Showing
1 changed file
with
64 additions
and
81 deletions
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java
| @@ -9,7 +9,6 @@ import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; | @@ -9,7 +9,6 @@ import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; | ||
| 9 | import software.amazon.awssdk.core.sync.RequestBody; | 9 | import software.amazon.awssdk.core.sync.RequestBody; |
| 10 | import software.amazon.awssdk.regions.Region; | 10 | import software.amazon.awssdk.regions.Region; |
| 11 | import software.amazon.awssdk.services.s3.S3Client; | 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; | 12 | import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; |
| 14 | import software.amazon.awssdk.services.s3.model.GetObjectRequest; | 13 | import software.amazon.awssdk.services.s3.model.GetObjectRequest; |
| 15 | import software.amazon.awssdk.services.s3.model.PutObjectRequest; | 14 | import software.amazon.awssdk.services.s3.model.PutObjectRequest; |
| @@ -32,38 +31,86 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> { | @@ -32,38 +31,86 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> { | ||
| 32 | super(id, config); | 31 | super(id, config); |
| 33 | } | 32 | } |
| 34 | 33 | ||
| 34 | + @Override | ||
| 35 | + protected void doInit() { | ||
| 36 | + // 补全 domain | ||
| 37 | + if (StrUtil.isEmpty(config.getDomain())) { | ||
| 38 | + config.setDomain(buildDomain()); | ||
| 39 | + } | ||
| 40 | + // 初始化 S3 客户端 | ||
| 41 | + client = S3Client.builder() | ||
| 42 | + .credentialsProvider(buildCredentials()) | ||
| 43 | + .region(Region.of("us-east-1")) // 必须填,但填什么都行,常见的值有 "us-east-1",不填会报错 | ||
| 44 | + .endpointOverride(URI.create(buildEndpoint())) | ||
| 45 | + //.serviceConfiguration(S3Configuration.builder().pathStyleAccessEnabled(true).build()) // Path-style 访问 | ||
| 46 | + .build(); | ||
| 47 | + } | ||
| 48 | + | ||
| 49 | + @Override | ||
| 50 | + public String upload(byte[] content, String path, String type) { | ||
| 51 | + // 构造 PutObjectRequest | ||
| 52 | + PutObjectRequest putRequest = PutObjectRequest.builder() | ||
| 53 | + .bucket(config.getBucket()) | ||
| 54 | + .key(path) | ||
| 55 | + .contentType(type) | ||
| 56 | + .contentLength((long) content.length) | ||
| 57 | + .build(); | ||
| 58 | + | ||
| 59 | + // 上传文件 | ||
| 60 | + client.putObject(putRequest, RequestBody.fromBytes(content)); | ||
| 61 | + // 拼接返回路径 | ||
| 62 | + return config.getDomain() + "/" + path; | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + @Override | ||
| 66 | + public void delete(String path) { | ||
| 67 | + DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder() | ||
| 68 | + .bucket(config.getBucket()) | ||
| 69 | + .key(path) | ||
| 70 | + .build(); | ||
| 71 | + client.deleteObject(deleteRequest); | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + @Override | ||
| 75 | + public byte[] getContent(String path) { | ||
| 76 | + GetObjectRequest getRequest = GetObjectRequest.builder() | ||
| 77 | + .bucket(config.getBucket()) | ||
| 78 | + .key(path) | ||
| 79 | + .build(); | ||
| 80 | + | ||
| 81 | + return IoUtil.readBytes(client.getObject(getRequest)); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + @Override | ||
| 85 | + public FilePresignedUrlRespDTO getPresignedObjectUrl(String path) { | ||
| 86 | + return new FilePresignedUrlRespDTO(getPresignedUrl(path, Duration.ofMinutes(10)), config.getDomain() + "/" + path); | ||
| 87 | + } | ||
| 88 | + | ||
| 35 | /** | 89 | /** |
| 36 | * 动态创建 S3Presigner | 90 | * 动态创建 S3Presigner |
| 37 | * | 91 | * |
| 38 | - * @param endpoint 节点地址 | ||
| 39 | - * @param accessKey 访问 Key | ||
| 40 | - * @param secretKey 访问 Secret | ||
| 41 | * @return S3Presigner | 92 | * @return S3Presigner |
| 42 | */ | 93 | */ |
| 43 | - private static S3Presigner createPresigner(String endpoint, String accessKey, String secretKey) { | 94 | + private S3Presigner createPresigner() { |
| 44 | return S3Presigner.builder() | 95 | return S3Presigner.builder() |
| 45 | - .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey))) | ||
| 46 | - .endpointOverride(URI.create(endpoint)) | 96 | + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret()))) |
| 97 | + .region(Region.of("us-east-1")) // 必须填,但填什么都行,常见的值有 "us-east-1",不填会报错 | ||
| 98 | + .endpointOverride(URI.create(buildEndpoint())) | ||
| 47 | .build(); | 99 | .build(); |
| 48 | } | 100 | } |
| 49 | 101 | ||
| 50 | /** | 102 | /** |
| 51 | * 生成动态的预签名上传 URL | 103 | * 生成动态的预签名上传 URL |
| 52 | * | 104 | * |
| 53 | - * @param bucket 存储 Bucket | ||
| 54 | - * @param path 相对路径 | ||
| 55 | - * @param duration 过期时间 | ||
| 56 | - * @param endpoint 节点地址 | ||
| 57 | - * @param accessKey 访问 Key | ||
| 58 | - * @param secretKey 访问 Secret | 105 | + * @param path 相对路径 |
| 106 | + * @param duration 过期时间 | ||
| 59 | * @return 生成的上传 URL | 107 | * @return 生成的上传 URL |
| 60 | */ | 108 | */ |
| 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)) { | 109 | + public String getPresignedUrl(String path, Duration duration) { |
| 110 | + try (S3Presigner presigner = createPresigner()) { | ||
| 64 | return presigner.presignPutObject(PutObjectPresignRequest.builder() | 111 | return presigner.presignPutObject(PutObjectPresignRequest.builder() |
| 65 | .signatureDuration(duration) | 112 | .signatureDuration(duration) |
| 66 | - .putObjectRequest(b -> b.bucket(bucket).key(path)) | 113 | + .putObjectRequest(b -> b.bucket(config.getBucket()).key(path)) |
| 67 | .build()).url().toString(); | 114 | .build()).url().toString(); |
| 68 | } | 115 | } |
| 69 | } | 116 | } |
| @@ -82,21 +129,6 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> { | @@ -82,21 +129,6 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> { | ||
| 82 | return StrUtil.format("https://{}.{}", config.getBucket(), config.getEndpoint()); | 129 | return StrUtil.format("https://{}.{}", config.getBucket(), config.getEndpoint()); |
| 83 | } | 130 | } |
| 84 | 131 | ||
| 85 | - @Override | ||
| 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 | /** | 132 | /** |
| 101 | * 基于 config 秘钥,构建 S3 客户端的认证信息 | 133 | * 基于 config 秘钥,构建 S3 客户端的认证信息 |
| 102 | * | 134 | * |
| @@ -120,53 +152,4 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> { | @@ -120,53 +152,4 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> { | ||
| 120 | return StrUtil.format("https://{}", config.getEndpoint()); | 152 | return StrUtil.format("https://{}", config.getEndpoint()); |
| 121 | } | 153 | } |
| 122 | 154 | ||
| 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(); | ||
| 132 | - | ||
| 133 | - // 上传文件 | ||
| 134 | - client.putObject(putRequest, RequestBody.fromBytes(content)); | ||
| 135 | - // 拼接返回路径 | ||
| 136 | - return config.getDomain() + "/" + path; | ||
| 137 | - } | ||
| 138 | - | ||
| 139 | - @Override | ||
| 140 | - public void delete(String path) { | ||
| 141 | - DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder() | ||
| 142 | - .bucket(config.getBucket()) | ||
| 143 | - .key(path) | ||
| 144 | - .build(); | ||
| 145 | - client.deleteObject(deleteRequest); | ||
| 146 | - } | ||
| 147 | - | ||
| 148 | - @Override | ||
| 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)); | ||
| 156 | - } | ||
| 157 | - | ||
| 158 | - @Override | ||
| 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); | ||
| 170 | - } | ||
| 171 | - | ||
| 172 | } | 155 | } |