Javaを使用して、特定のバケットにキーが存在するかどうかを確認したいと思います。APIを見ましたが、便利なメソッドはありません。使用しようとしましgetObject
たが、例外が発生しました。
16 に答える
公式JavaAPIに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();
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()
、適切な文字列を使用して確認できます(バージョンによって異なります)。
SDK V2で実際にオブジェクトを取得するという過負荷なしにそれを行う正しい方法は、S3Client.headObjectを使用することです。AWS変更ログによって公式に裏付けられています。
コード例:
public boolean exists(String bucket, String key) {
try {
HeadObjectResponse headResponse = client
.headObject(HeadObjectRequest.builder().bucket(bucket).key(key).build());
return true;
} catch (NoSuchKeyException e) {
return false;
}
}
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;
}
}
}.
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();
他の答えはAWSSDKv1用です。AWS SDK v2(現在は2.3.9)のメソッドは次のとおりです。
getObjectMetadata
およびdoesObjectExist
メソッドは現在v2SDKに含まれていないことに注意してください。したがって、それらはもはやオプションではありません。またはのいずれgetObject
かを使用する必要がありlistObjects
ます。
listObjects
現在、通話料金は。より12.5倍高くなっていgetObject
ます。ただし、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
メソッドはブール値を返しますが、例外をスローする可能性があります。
オブジェクトの使用。指定されたキーが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;
}
他の人が述べているように、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;
}
}
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
}
私が使用したときにもこの問題に直面しました
String BaseFolder = "3patti_Logs";
S3Object object = s3client.getObject(bucketName, BaseFolder);
エラーキーが見つかりません
叩いて試してみると
String BaseFolder = "3patti_Logs";
S3Object object = s3client.getObject(bucketName, BaseFolder+"/");
動作しました。このコードは1.9jarで動作します。それ以外の場合は、1.11に更新し、上記のようにdoesObjectExistを使用します。
jets3tライブラリを使用します。AWSSDKよりもはるかに簡単で堅牢です。このライブラリを使用して、s3service.getObjectDetails()を呼び出すことができます。これにより、オブジェクトの詳細(コンテンツではなく)のみがチェックおよび取得されます。オブジェクトが欠落している場合は404をスローします。したがって、その例外をキャッチして、アプリで処理できます。
ただし、これを機能させるには、そのバケットのユーザーがListBucketにアクセスできる必要があります。GetObjectアクセスだけでは機能しません。その理由は、ListBucketにアクセスできない場合、Amazonはキーの存在を確認できないようにするためです。キーが存在するかどうかを知るだけで、悪意のあるユーザーにとっても十分な場合があります。したがって、ListBucketにアクセスできない限り、アクセスすることはできません。
または、 Minio-Javaクライアントライブラリとそのオープンソースを使用して、 AWSS3APIと互換性を持たせることもできます。
Minio-JavaStatObject.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 class GetObject {
public static void main(String[] args)
throws NoSuchAlgorithmException, IOException, InvalidKeyException, XmlPullParserException, MinioException {
// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are
// dummy values, please replace them with original values.
// Set s3 endpoint, region is calculated automatically
MinioClient s3Client = new MinioClient("https://s3.amazonaws.com", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY");
InputStream stream = 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();
}
}
お役に立てば幸いです。
免責事項:私はMinioで働いています