AWS Amazon S3 Java SDK - 上传大文件时过期时刷新凭证/令牌
AWS Amazon S3 Java SDK - Refresh credentials / token when expired while uploading large file
我正在尝试将一个大文件上传到一个使用令牌的服务器,该令牌会在 10 分钟后过期,因此如果我上传一个小文件它会起作用因此如果文件比我大我会得到一些问题,将在访问被拒绝时尝试永远上传
所以我需要刷新 BasicAWSCredentials 中的令牌,它用于 AWSStaticCredentialsProvider 因此我不确定我该如何做吧,请帮忙 =)
值得一提的是,我们使用本地服务器(不是亚马逊云)提供令牌,为了方便起见,我们使用亚马逊的代码。
这是我的代码:
public void uploadMultipart(File file) throws Exception {
//this method will give you a initial token for a given user,
//than calculates when a new token is needed and will refresh it just when necessary
String token = getUsetToken();
String existingBucketName = myTenant.toLowerCase() + ".package.upload";
String endPoint = urlAPI + "s3/buckets/";
String strSize = FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(file));
System.out.println("File size: " + strSize);
AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(endPoint, null);//note: Region has to be null
//AWSCredentialsProvider
BasicAWSCredentials sessionCredentials = new BasicAWSCredentials(token, "NOT_USED");//secretKey should be set to NOT_USED
AmazonS3 s3 = AmazonS3ClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(sessionCredentials))
.withEndpointConfiguration(endpointConfiguration)
.enablePathStyleAccess()
.build();
int maxUploadThreads = 5;
TransferManager tm = TransferManagerBuilder
.standard()
.withS3Client(s3)
.withMultipartUploadThreshold((long) (5 * 1024 * 1024))
.withExecutorFactory(() -> Executors.newFixedThreadPool(maxUploadThreads))
.build();
PutObjectRequest request = new PutObjectRequest(existingBucketName, file.getName(), file);
//request.putCustomRequestHeader("Access-Token", token);
ProgressListener progressListener = progressEvent -> System.out.println("Transferred bytes: " + progressEvent.getBytesTransferred());
request.setGeneralProgressListener(progressListener);
Upload upload = tm.upload(request);
LocalDateTime uploadStartedAt = LocalDateTime.now();
log.info("Starting upload at: " + uploadStartedAt);
try {
upload.waitForCompletion();
//upload.waitForUploadResult();
log.info("Upload completed. " + strSize);
} catch (Exception e) {//AmazonClientException
log.error("Error occurred while uploading file - " + strSize);
e.printStackTrace();
}
}
上传文件(或多部分文件的一部分)时,您使用的凭据必须持续足够长的时间才能完成上传。您无法刷新凭据,因为没有方法可以更新 AWS S3,您正在为已签名的请求使用新凭据。
您可以将上传分成更小的文件,这样上传速度会更快。然后只上传 X 部分。刷新您的凭据并上传 Y 部分。重复直到上传所有部分。然后您将需要通过组合部件(这是一个单独的命令)来完成。这不是一个完美的解决方案,因为无法准确控制传输速度,这意味着您将不得不编写自己的上传代码(这并不难)。
已找到解决方案!
我找到了一种方法来让它工作,老实说,我对结果很满意,我用大文件 (50gd.zip) 做了很多测试,并且在每个场景中都工作得很好
我的解决方案是,删除以下行: BasicAWSCredentials sessionCredentials = new BasicAWSCredentials(token, "NOT_USED");
AWSCredentials
是一个接口,所以我们可以用动态的东西覆盖它,当 token 过期并且需要一个新的新令牌时的逻辑保存在里面getToken() 方法意味着您可以每次调用而不会造成任何伤害
AWSCredentials sessionCredentials = new AWSCredentials() {
@Override
public String getAWSAccessKeyId() {
try {
return getToken(); //getToken() method return a string
} catch (Exception e) {
return null;
}
}
@Override
public String getAWSSecretKey() {
return "NOT_USED";
}
};
我正在尝试将一个大文件上传到一个使用令牌的服务器,该令牌会在 10 分钟后过期,因此如果我上传一个小文件它会起作用因此如果文件比我大我会得到一些问题,将在访问被拒绝时尝试永远上传
所以我需要刷新 BasicAWSCredentials 中的令牌,它用于 AWSStaticCredentialsProvider 因此我不确定我该如何做吧,请帮忙 =)
值得一提的是,我们使用本地服务器(不是亚马逊云)提供令牌,为了方便起见,我们使用亚马逊的代码。
这是我的代码:
public void uploadMultipart(File file) throws Exception {
//this method will give you a initial token for a given user,
//than calculates when a new token is needed and will refresh it just when necessary
String token = getUsetToken();
String existingBucketName = myTenant.toLowerCase() + ".package.upload";
String endPoint = urlAPI + "s3/buckets/";
String strSize = FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(file));
System.out.println("File size: " + strSize);
AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(endPoint, null);//note: Region has to be null
//AWSCredentialsProvider
BasicAWSCredentials sessionCredentials = new BasicAWSCredentials(token, "NOT_USED");//secretKey should be set to NOT_USED
AmazonS3 s3 = AmazonS3ClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(sessionCredentials))
.withEndpointConfiguration(endpointConfiguration)
.enablePathStyleAccess()
.build();
int maxUploadThreads = 5;
TransferManager tm = TransferManagerBuilder
.standard()
.withS3Client(s3)
.withMultipartUploadThreshold((long) (5 * 1024 * 1024))
.withExecutorFactory(() -> Executors.newFixedThreadPool(maxUploadThreads))
.build();
PutObjectRequest request = new PutObjectRequest(existingBucketName, file.getName(), file);
//request.putCustomRequestHeader("Access-Token", token);
ProgressListener progressListener = progressEvent -> System.out.println("Transferred bytes: " + progressEvent.getBytesTransferred());
request.setGeneralProgressListener(progressListener);
Upload upload = tm.upload(request);
LocalDateTime uploadStartedAt = LocalDateTime.now();
log.info("Starting upload at: " + uploadStartedAt);
try {
upload.waitForCompletion();
//upload.waitForUploadResult();
log.info("Upload completed. " + strSize);
} catch (Exception e) {//AmazonClientException
log.error("Error occurred while uploading file - " + strSize);
e.printStackTrace();
}
}
上传文件(或多部分文件的一部分)时,您使用的凭据必须持续足够长的时间才能完成上传。您无法刷新凭据,因为没有方法可以更新 AWS S3,您正在为已签名的请求使用新凭据。
您可以将上传分成更小的文件,这样上传速度会更快。然后只上传 X 部分。刷新您的凭据并上传 Y 部分。重复直到上传所有部分。然后您将需要通过组合部件(这是一个单独的命令)来完成。这不是一个完美的解决方案,因为无法准确控制传输速度,这意味着您将不得不编写自己的上传代码(这并不难)。
已找到解决方案!
我找到了一种方法来让它工作,老实说,我对结果很满意,我用大文件 (50gd.zip) 做了很多测试,并且在每个场景中都工作得很好
我的解决方案是,删除以下行: BasicAWSCredentials sessionCredentials = new BasicAWSCredentials(token, "NOT_USED");
AWSCredentials
是一个接口,所以我们可以用动态的东西覆盖它,当 token 过期并且需要一个新的新令牌时的逻辑保存在里面getToken() 方法意味着您可以每次调用而不会造成任何伤害
AWSCredentials sessionCredentials = new AWSCredentials() {
@Override
public String getAWSAccessKeyId() {
try {
return getToken(); //getToken() method return a string
} catch (Exception e) {
return null;
}
}
@Override
public String getAWSSecretKey() {
return "NOT_USED";
}
};