web-dev-qa-db-ja.com

Javaを使用して、指定されたキーが特定のS3バケットに存在するかどうかを確認する方法

Javaを使用して、特定のバケットにキーが存在するかどうかを確認したいと思います。 APIを見ましたが、便利なメソッドはありません。 getObjectを使用しようとしましたが、例外がスローされました。

70
in His Steps

Jets3tライブラリを使用します。 AWS SDKよりもはるかに簡単で堅牢です。このライブラリを使用して、s3service.getObjectDetails()を呼び出すことができます。これにより、オブジェクトの内容のみではなく、オブジェクトの詳細のみがチェックおよび取得されます。オブジェクトがない場合、404をスローします。そのため、その例外をキャッチして、アプリで処理できます。

ただし、これが機能するためには、そのバケットのユーザーにListBucketアクセス権が必要です。 GetObjectアクセスだけは機能しません。その理由は、ListBucketにアクセスできない場合、Amazonはキーの存在を確認できないようにするためです。キーが存在するかどうかを知るだけでも、悪意のあるユーザーにとっては十分な場合があります。したがって、ListBucketにアクセスできない限り、アクセスすることはできません。

7
sethu

公式のJava AP​​Iに doesObjectExist メソッドが追加されました。

楽しい!

236
lmichelbacher

更新:

それを確認する新しい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を提供していないことです。例外に関するドキュメントのみです。

56

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;
}
21
user979051

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();
    S3Object 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()を使用して、適切な文字列を確認できます(バージョンによって異なります)。

11
Paul Draper

キーとしてListObjectsRequest設定Prefixを使用します。

.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;
            }
        }
    }.
5
user34402

PHP(質問はJavaであることは知っていますが、Googleがここに持ってきました)には、ストリームラッパーとfile_existsを使用できます

$bucket = "MyBucket";
$key = "MyKey";
$s3 = Aws\S3\S3Client->factory([...]);
$s3->registerStreamWrapper();
$keyExists = file_exists("s3://$bucket/$key");
5
Rich Remer

この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;
}
4
c0mrade

パスをバケットとオブジェクトに分けます。メソッドdoesBucketExistを使用してバケットをテストします。リストのサイズを使用してオブジェクトをテストします(存在しない場合は0)。したがって、このコードは次のことを行います。

String bucket = ...;
String objectInBucket = ...;
AmazonS3 s3 = new AmazonS3Client(...);
return s3.doesBucketExist(bucket) 
       && !s3.listObjects(bucket, objectInBucket).getObjectSummaries().isEmpty();
3
roee

オブジェクトのイスティングの使用。指定したキーがAWS S3に存在するかどうかを確認する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;
    }
3
Kaustuv

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

        }
1
Dhwaneel

他の答えはAWS SDK v1に対するものです。以下は、AWS SDK v2(現在2.3.9)のメソッドです。

getObjectMetadataおよびdoesObjectExistメソッドは、現在v2 SDKにはないことに注意してください!したがって、これらはオプションではありません。 getObjectまたはlistObjectsのいずれかを使用する必要があります。

listObjects呼び出しは、現在、getObjectの12.5倍の費用がかかります。ただし、AWSはダウンロードされたデータに対しても課金し、getObjectファイルが存在する場合の価格を引き上げます。ファイルが存在する可能性が非常に低い限り(たとえば、新しいUUIDキーをランダムに生成し、それが取得されないことを再確認する必要がある場合)、getObjectを呼び出すことは私の計算では大幅に安くなります。

ただし、念のために、range()仕様を追加して、AWSにファイルの数バイトのみを送信するように依頼しています。私の知る限り、SDKは常にこれを尊重し、ファイル全体のダウンロードに対して料金を請求することはありません。しかし、私はそれを確認していませんので、あなた自身の責任でその動作に依存してください! (また、S3オブジェクトの長さが0バイトの場合、rangeがどのように動作するかわかりません。)

    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が他の場所で宣言および初期化されていることを前提としています。メソッドはブール値を返しますが、例外をスローできます。

0
Bampfer

オブジェクトを実際に取得するオーバーロードなしでSDK V2でそれを行う正しい方法は、 S3Client.headObject を使用することです。 AWS Change Log によって公式に支援されています。

0
E.T

または、 Minio-Java クライアントライブラリ、そのオープンソース、AWS S3 APIとの互換性を使用できます。

Minio-Java StatObject.Java の例を使用できます。

 import io.minio.MinioClient; 
 import io.minio.errors.MinioException; 
 
 import Java.io.InputStream; 
 import Java .io.IOException; 
 import Java.security.NoSuchAlgorithmException; 
 import Java.security.InvalidKeyException; 
 
 import org.xmlpull.v1.XmlPullParserException; 
 
 
 publicクラスGetObject {
 public static void main(String [] args)
 throws 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 stream = s3Client.getObject( " my-bucketname "、" my-objectname "); 
 
 byte [] buf = ne w byte [16384]; 
 int bytesRead; 
 while((bytesRead = stream.read(buf、0、buf.length))> = 0){
 System.out .println(new String(buf、0、bytesRead)); 
} 
 
 stream.close(); 
} 
} 

役に立てば幸いです。

免責事項: Minio で働いています

0
koolhead17