Javaを使用して、特定のバケットにキーが存在するかどうかを確認したいと思います。APIを見ましたが、便利なメソッドはありません。使用しようとしましgetObject
たが、例外が発生しました。
回答:
jets3tライブラリを使用します。AWSSDKよりもはるかに簡単で堅牢です。このライブラリを使用すると、s3service.getObjectDetails()を呼び出すことができます。これにより、オブジェクトの詳細(コンテンツではなく)のみがチェックおよび取得されます。オブジェクトが欠落している場合は404をスローします。したがって、その例外をキャッチして、アプリで処理できます。
ただし、これを機能させるには、そのバケットのユーザーがListBucketにアクセスできる必要があります。GetObjectアクセスだけでは機能しません。その理由は、ListBucketにアクセスできない場合、Amazonはキーの存在を確認できないようにするためです。キーが存在するかどうかを知るだけで、悪意のあるユーザーにとっても十分な場合があります。したがって、ListBucketにアクセスできない限り、アクセスすることはできません。
今ありますdoesObjectExistの公式Java APIの方法が。
楽しい!
doesObjectExist
2.xSDK(現在はv2.3.9)から削除されたようです。
更新:
それをチェックするための新しいAPIがあるようです。このページの別の回答を参照してください:https://stackoverflow.com/a/36653034/435605
元の投稿:
使用する errorCode.equals("NoSuchKey")
try {
AmazonS3 s3 = new AmazonS3Client(new ClasspathPropertiesFileCredentialsProvider());
String bucketName = getBucketName();
s3.createBucket(bucketName);
S3Object object = s3.getObject(bucketName, getKey());
} catch (AmazonServiceException e) {
String errorCode = e.getErrorCode();
if (!errorCode.equals("NoSuchKey")) {
throw e;
}
Logger.getLogger(getClass()).debug("No such key!!!", e);
}
例外についての注意:例外はフロー制御に使用すべきではないことを私は知っています。問題は、AmazonがこのフローをチェックするためのAPIを提供していなかったことです。例外に関するドキュメントだけです。
errorMessage
が「NotFound」に設定されているのがわかりerrorCode
ますが、はnullです。
NoSuchKey
。S3エラーコードの明確なリストについては、ドキュメントを参照してください:docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
AWS SDKを使用するには、getObjectMetadataメソッドを使用します。キーが存在しない場合、メソッドはAmazonServiceExceptionをスローします。
private AmazonS3 s3;
...
public boolean exists(String path, String name) {
try {
s3.getObjectMetadata(bucket, getS3Path(path) + name);
} catch(AmazonServiceException e) {
return false;
}
return true;
}
Amazon Java SDK 1.10+ではgetStatusCode()
、HTTP応答のステータスコードを取得するために使用できます。オブジェクトが存在しない場合は404になります。
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.AmazonS3Exception;
import org.apache.http.HttpStatus;
try {
AmazonS3 s3 = new AmazonS3Client();
ObjectMetadata object = s3.getObjectMetadata("my-bucket", "my-client");
} catch (AmazonS3Exception e) {
if (e.getStatusCode() == HttpStatus.SC_NOT_FOUND) {
// bucket/key does not exist
} else {
throw e;
}
}
getObjectMetadata()
消費するリソースが少なく、のように応答を閉じる必要はありませんgetObject()
。
以前のバージョンでgetErrorCode()
は、適切な文字列を使用して確認できます(バージョンによって異なります)。
ListObjectsRequest設定プレフィックスをキーとして使用します。
.NETコード:
public bool Exists(string key)
{
using (Amazon.S3.AmazonS3Client client = (Amazon.S3.AmazonS3Client)Amazon.AWSClientFactory.CreateAmazonS3Client(m_accessKey, m_accessSecret))
{
ListObjectsRequest request = new ListObjectsRequest();
request.BucketName = m_bucketName;
request.Prefix = key;
using (ListObjectsResponse response = client.ListObjects(request))
{
foreach (S3Object o in response.S3Objects)
{
if( o.Key == key )
return true;
}
return false;
}
}
}.
このJavaコードは、キー(ファイル)がs3バケットに存在するかどうかを確認します。
public static boolean isExistS3(String accessKey, String secretKey, String bucketName, String file) {
// Amazon-s3 credentials
AWSCredentials myCredentials = new BasicAWSCredentials(accessKey, secretKey);
AmazonS3Client s3Client = new AmazonS3Client(myCredentials);
ObjectListing objects = s3Client.listObjects(new ListObjectsRequest().withBucketName(bucketName).withPrefix(file));
for (S3ObjectSummary objectSummary: objects.getObjectSummaries()) {
if (objectSummary.getKey().equals(file)) {
return true;
}
}
return false;
}
パスをバケットとオブジェクトに分割します。メソッドを使用してバケットをdoesBucketExist
テストし、リストのサイズを使用してオブジェクトをテストします(存在しない場合は0)。したがって、このコードは次のようになります。
String bucket = ...;
String objectInBucket = ...;
AmazonS3 s3 = new AmazonS3Client(...);
return s3.doesBucketExist(bucket)
&& !s3.listObjects(bucket, objectInBucket).getObjectSummaries().isEmpty();
オブジェクトの使用。指定されたキーがAWSS3に存在するかどうかを確認するJava関数。
boolean isExist(String key)
{
ObjectListing objects = amazonS3.listObjects(new ListObjectsRequest().withBucketName(bucketName).withPrefix(key));
for (S3ObjectSummary objectSummary : objects.getObjectSummaries())
{
if (objectSummary.getKey().equals(key))
{
return true;
}
}
return false;
}
jetS3t APIのisObjectInBucket()メソッドを使用してこれを行う簡単な方法があります。
サンプルコード:
ProviderCredentials awsCredentials = new AWSCredentials(
awsaccessKey,
awsSecretAcessKey);
// REST implementation of S3Service
RestS3Service restService = new RestS3Service(awsCredentials);
// check whether file exists in bucket
if (restService.isObjectInBucket(bucket, objectKey)) {
//your logic
}
その他の回答はAWSSDKv1用です。AWS SDK v2(現在は2.3.9)のメソッドは次のとおりです。
getObjectMetadata
およびdoesObjectExist
メソッドは現在v2SDKに含まれていないことに注意してください。したがって、これらはもはやオプションではありません。getObject
またはのいずれかを使用する必要がありlistObjects
ます。
listObjects
現在、通話料金はgetObject
。より12.5倍高くなっています。ただし、AWSはダウンロードされたデータに対しても課金するためgetObject
、ファイルが存在する場合の料金が高くなります。ファイルが存在する可能性が非常に低い限り(たとえば、新しいUUIDキーをランダムに生成し、それが取得されていないことを再確認する必要がある場合)、getObject
私の計算ではは大幅に安価です。
念のため、range()
AWSにファイルの数バイトのみを送信するように要求する仕様を追加しました。私の知る限り、SDKは常にこれを尊重し、ファイル全体のダウンロードに対して料金を請求することはありません。しかし、私はそれを確認していませんので、あなた自身の責任でその行動に頼ってください!(また、range
S3オブジェクトの長さが0バイトの場合の動作もわかりません。)
private boolean sanityCheckNewS3Key(String bucket, String key) {
ResponseInputStream<GetObjectResponse> resp = null;
try {
resp = s3client.getObject(GetObjectRequest.builder()
.bucket(bucket)
.key(key)
.range("bytes=0-3")
.build());
}
catch (NoSuchKeyException e) {
return false;
}
catch (AwsServiceException se) {
throw se;
}
finally {
if (resp != null) {
try {
resp.close();
} catch (IOException e) {
log.warn("Exception while attempting to close S3 input stream", e);
}
}
}
return true;
}
}
注:このコードはs3Client
、log
他の場所で宣言および初期化されていることを前提としています。メソッドはブール値を返しますが、例外をスローする可能性があります。
s3Client.headObject()
これを行うためのがV2にあるようです:stackoverflow.com/a/56949742/9814131、そしてS3Exception
githubの問題github.com/aws/aws-sdk-に従ってオブジェクトが存在するかどうかを確認するためにのステータスコード404をチェックしますjava-v2 / issues / 297。ただし、オーバーヘッドが0〜3バイトと非常に少ないため、より進歩的だと思います。
SDK V2で実際にオブジェクトを取得するという過負荷なしにそれを行う正しい方法は、S3Client.headObjectを使用することです。AWS変更ログによって公式に裏付けられています。
私が使用したときにもこの問題に直面しました
String BaseFolder = "3patti_Logs";
S3Object object = s3client.getObject(bucketName, BaseFolder);
エラーキーが見つかりません
叩いて試してみると
String BaseFolder = "3patti_Logs";
S3Object object = s3client.getObject(bucketName, BaseFolder+"/");
それは機能しました、このコードは1.9 jarで機能しています、それ以外の場合は1.11に更新し、上記のようにdoesObjectExistを使用します
他の人が言及したように、AWS S3 Java SDK 2.10+の場合、HeadObjectRequestを使用できますオブジェクトをして、S3バケットにファイルがあるかどうかを確認できます。これは、実際にファイルを取得することなく、GETリクエストのように機能します。
他の人が実際に上記のコードを追加していないため、サンプルコード:
public boolean existsOnS3 () throws Exception {
try {
S3Client s3Client = S3Client.builder ().credentialsProvider (...).build ();
HeadObjectRequest headObjectRequest = HeadObjectRequest.builder ().bucket ("my-bucket").key ("key/to/file/house.pdf").build ();
HeadObjectResponse headObjectResponse = s3Client.headObject (headObjectRequest);
return headObjectResponse.sdkHttpResponse ().isSuccessful ();
}
catch (NoSuchKeyException e) {
//Log exception for debugging
return false;
}
}
headObjectResponse
。throws Exception
同様に必要ありません。
または、Minio-Javaクライアントライブラリとそのオープンソースを使用して、AWS S3APIと互換性を持たせることもできます。
Minio-JavaStatObject.javaの例を同じように使用できます。
import io.minio.MinioClient; import io.minio.errors.MinioException; インポートjava.io.InputStream; インポートjava.io.IOException; インポートjava.security.NoSuchAlgorithmException; インポートjava.security.InvalidKeyException; import org.xmlpull.v1.XmlPullParserException; パブリッククラスGetObject { public static void main(String [] args) NoSuchAlgorithmException、IOException、InvalidKeyException、XmlPullParserException、MinioException {をスローします //注:YOUR-ACCESSKEYID、YOUR-SECRETACCESSKEY、my-bucketnameは //ダミー値。元の値に置き換えてください。 // s3エンドポイントを設定し、領域は自動的に計算されます MinioClient s3Client = new MinioClient( "https://s3.amazonaws.com"、 "YOUR-ACCESSKEYID"、 "YOUR-SECRETACCESSKEY"); InputStreamストリーム= s3Client.getObject( "my-bucketname"、 "my-objectname"); byte [] buf = new byte [16384]; int bytesRead; while((bytesRead = stream.read(buf、0、buf.length))> = 0){ System.out.println(new String(buf、0、bytesRead)); } stream.close(); } }
お役に立てば幸いです。