Javaを使用して、特定のバケットにキーが存在するかどうかを確認したいと思います。 APIを見ましたが、便利なメソッドはありません。 getObject
を使用しようとしましたが、例外がスローされました。
Jets3tライブラリを使用します。 AWS SDKよりもはるかに簡単で堅牢です。このライブラリを使用して、s3service.getObjectDetails()を呼び出すことができます。これにより、オブジェクトの内容のみではなく、オブジェクトの詳細のみがチェックおよび取得されます。オブジェクトがない場合、404をスローします。そのため、その例外をキャッチして、アプリで処理できます。
ただし、これが機能するためには、そのバケットのユーザーにListBucketアクセス権が必要です。 GetObjectアクセスだけは機能しません。その理由は、ListBucketにアクセスできない場合、Amazonはキーの存在を確認できないようにするためです。キーが存在するかどうかを知るだけでも、悪意のあるユーザーにとっては十分な場合があります。したがって、ListBucketにアクセスできない限り、アクセスすることはできません。
公式のJava APIに doesObjectExist メソッドが追加されました。
楽しい!
更新:
それを確認する新しい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を提供していないことです。例外に関するドキュメントのみです。
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();
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()
を使用して、適切な文字列を確認できます(バージョンによって異なります)。
キーとして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;
}
}
}.
PHP(質問はJavaであることは知っていますが、Googleがここに持ってきました)には、ストリームラッパーとfile_existsを使用できます
$bucket = "MyBucket";
$key = "MyKey";
$s3 = Aws\S3\S3Client->factory([...]);
$s3->registerStreamWrapper();
$keyExists = file_exists("s3://$bucket/$key");
この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();
オブジェクトのイスティングの使用。指定したキーが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;
}
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
}
他の答えは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
が他の場所で宣言および初期化されていることを前提としています。メソッドはブール値を返しますが、例外をスローできます。
オブジェクトを実際に取得するオーバーロードなしでSDK V2でそれを行う正しい方法は、 S3Client.headObject を使用することです。 AWS Change Log によって公式に支援されています。
または、 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 で働いています