S3へファイルをアップロード(TransferManagerを使用)するコードを書く機会がありました。その際に困った点について共有したいと思います。
実際はコードを書いている際に困ったわけではなく、運用している際に困った話です。
(つまりテストなどで逃しやすい)
さっそく結論から
1.TransferManagerは必ずtransferManager.shutdownNow()でシャットダウンする。
2.amazonS3Client.getCachedResponseMetadata()でS3ResponseMetadataを取得しログに出力しておく。
3.マルチパートアップロードされないように閾値を変更しておく。(アップロードサイズとの兼ね合い)
コード例
private void fileUploadToS3(String s3UploadFilePath, MultipartFile multipartFile) throws Exception {
String s3BucketName = "test_bucket";
AmazonS3Client amazonS3Client = new AmazonS3Client();
PutObjectRequest putObjectRequest = null;
try (
InputStream multipartFileInStream = multipartFile.getInputStream()) {
TransferManager transferManager = new TransferManager(amazonS3Client);
TransferManagerConfiguration config = new TransferManagerConfiguration();
// ResponseMetadataを取得するために閾値変更
Long multipartUploadThreshold = 50L * 1000L * 1000L
transferManagerConfiguration.setMultipartUploadThreshold(multipartUploadThreshold);
transferManager.setConfiguration(transferManagerConfiguration);
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(multipartFile.getSize());
putObjectRequest = new PutObjectRequest(s3BucketName, s3UploadFilePath, multipartFileInStream, objectMetadata);
Upload upload = transferManager.upload(putObjectRequest);
upload.waitForUploadResult();
} finally {
S3ResponseMetadata s3ResponseMetadata = amazonS3Client.getCachedResponseMetadata(putObjectRequest);
if (s3ResponseMetadata != null) {
// AWSサポートへの問い合わせに使用する。(SLF4Jとか使ってオブジェクトごと出したほうがいいかも)
System.out.println("RequestId : "+ s3ResponseMetadata.getRequestId() + ", HostId : " + s3ResponseMetadata.getHostId());
} else {
System.out.println("ResponseMetadata :null");
}
// シャットダウンしないとExceptionの素
transferManager.shutdownNow(false);
}
}
簡単にですが説明
1.について
シャットダウンしない場合、アップロードが頻繁に起きた際にException発生の原因になる。ドキュメントの例をよく見るとこっそり必ず入ってました。
2.について
S3アップロードの失敗など、調査でAWSサポートへ問い合わせる場合に必要になる。
3.について
閾値を超えてマルチパートアップロードになった場合2.で取得予定のS3ResponseMetadataが取得できません。
TransferManagerでのアップロードではアップロードファイルサイズによって単体アップロードかマルチパートアップロードかを切り替えているため、必ず取得したい場合、閾値を上げる必要があります。(デフォルト16MB)
ただし、サイズが大きい場合マルチパートアップロードの恩恵を受けるために致し方なし?
今気づきましたが、S3ResponseMetadata、ResponseMetadataのドキュメントにAWSサポートで使用するっぽいことって書いてますね。
Returns the Amazon S3 host ID, providing additional debugging information about how a request was handled.
Returns the AWS request ID contained in this response metadata object. AWS request IDs can be used in the event a service call isn't working as expected and you need to work with AWS support to debug an issue.
余談:Qiita投稿用に書いてたものをコピペしたら、Qiitaでの書式がそのままコピーされた。