问题
使用S3 V2的SDK来进行简单文件上传(2021年2月24日,现在AWS的SDK版本也是两个版本,一个V1,一个V2,这里使用V2)。S3文件上传有两种方式:
- 单一文件上传
- 文件分块上传:就是开一个上传任务,然后把单个文件拆成几块并发上传。
思路
- 准备上传客户端:S3Client
- 构建上传请求:PutObjectRequest
- 使用S3Client进行单文件上传
解决
S3Client
授权环境变量
在构建S3客户端之前,需要对客户端进行授权,AWS授权方式很多,这里采用环境变量的方式进行授权,即配置两个Java环境变量,然后,S3Client就拥有了S3的相关权限。具体环境变量为:
AWS_ACCESS_KEY_ID=;AWS_SECRET_ACCESS_KEY=
只要配置这两个环境变量,然后,就不需要在代码中写死aws相关授权信息了,如果程序是运行在EC2上面,还可以通过AWS控制台直接对EC2实例进行授权。在IDEA配置环境变量如下方式:
Maven
<properties>
<aws.java.sdk.version>2.16.5</aws.java.sdk.version>
</properties>
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>sdk-core</artifactId>
<version>${aws.java.sdk.version}</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>${aws.java.sdk.version}</version>
</dependency>
</dependencies>
Java
构建S3Client:
application.yml
aws:
mediaConvert:
region: ap-southeast-1
Config.java
@Value("${aws.mediaConvert.region}")
private String region;
@Bean
public S3Client s3Client() {
return S3Client.builder().region(Region.of(region)).build();
}
AwsFileServiceImpl.java
设置文件桶并创建:
private void handBucket(String bucketName, S3Client s3Client) {
try {
s3Client.headBucket(HeadBucketRequest.builder().bucket(bucketName).build());
} catch (NoSuchBucketException e) {
AbortIncompleteMultipartUpload.Builder abortIncompleteMultipartUploadBuilder =
AbortIncompleteMultipartUpload.builder();
abortIncompleteMultipartUploadBuilder.daysAfterInitiation(7);
LifecycleRule.Builder lifecycleRuleBuilder =
LifecycleRule.builder()
.id("AbortIncompleteMultipartUpload")
.status(ExpirationStatus.ENABLED)
.abortIncompleteMultipartUpload(abortIncompleteMultipartUploadBuilder.build());
if (bucketName.equals(templateBucketName)) {
// 临时文件桶设置过期时间
lifecycleRuleBuilder.expiration(LifecycleExpiration.builder().days(15).build());
}
// 设置文件桶访问权限
BucketLifecycleConfiguration configuration =
BucketLifecycleConfiguration.builder().rules(lifecycleRuleBuilder.build()).build();
s3Client.createBucket(CreateBucketRequest.builder().bucket(bucketName).build());
s3Client.putPublicAccessBlock(
PutPublicAccessBlockRequest.builder()
.bucket(bucketName)
.publicAccessBlockConfiguration(
PublicAccessBlockConfiguration.builder()
.blockPublicAcls(true)
.ignorePublicAcls(true)
.blockPublicAcls(true)
.restrictPublicBuckets(true)
.build())
.build());
s3Client.putBucketLifecycleConfiguration(
PutBucketLifecycleConfigurationRequest.builder()
.bucket(bucketName)
.lifecycleConfiguration(configuration)
.build());
// Enable Transfer Acceleration for the specified bucket.
s3Client.putBucketAccelerateConfiguration(
PutBucketAccelerateConfigurationRequest.builder()
.bucket(bucketName)
.accelerateConfiguration(
AccelerateConfiguration.builder().status(BucketAccelerateStatus.ENABLED).build())
.build());
}
}
上传单文件到AWS s3:
@Resource private S3Client s3Client;
public void uploadSingleFile(String bucketName, String keyName, MultipartFile file) {
File tmpFile = null;
try {
tmpFile = File.createTempFile("uploadFileTemp", ".tmp");
file.transferTo(tmpFile);
handBucket(bucketName, s3Client);
String contentType = file.getContentType();
PutObjectRequest.Builder putObjectRequestBuilder =
PutObjectRequest.builder()
.bucket(bucketName)
.key(keyName)
.contentType(contentType)
// 设置 aws s3 智能分层 方式存储文件
.storageClass(StorageClass.INTELLIGENT_TIERING);
PutObjectRequest request = putObjectRequestBuilder.build();
// 开始同步上传文件
PutObjectResponse putObjectResponse =
s3Client.putObject(request, RequestBody.fromFile(tmpFile));
} catch (SdkClientException | IOException e) {
// 异常处理...
} finally {
if (tmpFile != null && tmpFile.exists()) {
if (!tmpFile.delete()) {
// 临时文件删除失败
}
}
}
}