Java를 사용하여 주어진 버킷에 키가 있는지 확인하고 싶습니다. API를 살펴 봤지만 유용한 방법이 없습니다. 사용하려고했지만 getObject
예외가 발생했습니다.
Java를 사용하여 주어진 버킷에 키가 있는지 확인하고 싶습니다. API를 살펴 봤지만 유용한 방법이 없습니다. 사용하려고했지만 getObject
예외가 발생했습니다.
답변:
jets3t 라이브러리를 사용하십시오. AWS SDK보다 훨씬 쉽고 강력합니다. 이 라이브러리를 사용하여 s3service.getObjectDetails ()를 호출 할 수 있습니다. 이것은 개체의 내용이 아닌 개체의 세부 정보 만 확인하고 검색합니다. 객체가 없으면 404가 발생합니다. 따라서 해당 예외를 포착하고 앱에서 처리 할 수 있습니다.
그러나 이것이 작동하려면 해당 버킷의 사용자에 대한 ListBucket 액세스 권한이 있어야합니다. GetObject 액세스 만 작동하지 않습니다. 그 이유는 Amazon이 ListBucket 액세스 권한이없는 경우 키가 있는지 확인하지 못하도록하기 때문입니다. 키가 있는지 여부를 아는 것만으로도 어떤 경우에는 악의적 인 사용자에게도 충분합니다. 따라서 ListBucket 액세스 권한이 없으면 그렇게 할 수 없습니다.
이제 공식 Java API에 doesObjectExist 메소드가 있습니다.
즐겨!
doesObjectExist
2.x SDK (현재 v2.3.9)에서 Amazon이 제거 된 것 같습니다 .
최신 정보:
그것을 확인하는 새로운 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
가 "Not Found"로 설정되어 있지만 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 설정 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;
}
}
}.
이 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();
Object isting 사용. 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
. 하지만 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
선언되고 다른 곳에서 초기화됩니다. 메서드는 부울을 반환하지만 예외를 throw 할 수 있습니다.
s3Client.headObject()
: V2에서이해야 할 일 stackoverflow.com/a/56949742/9814131을 , 당신은 확인합니다 S3Exception
개체가 GitHub의 발행에 따라 존재하는지 확인의 상태 코드 (404)를 github.com/aws/aws-sdk- java-v2 / issues / 297 . 그러나 0-3 바이트만큼 오버 헤드가 거의 없기 때문에 더 진보적이라고 생각합니다.
실제로 객체를 가져 오는 오버로드없이 SDK V2에서이를 수행하는 올바른 방법은 S3Client.headObject 를 사용하는 것 입니다. AWS Change Log에서 공식적으로 지원합니다 .
나는 또한 내가 사용할 때이 문제에 직면했다.
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 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; 공용 클래스 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 = 새 바이트 [16384]; int bytesRead; while ((bytesRead = stream.read (buf, 0, buf.length))> = 0) { System.out.println (new String (buf, 0, bytesRead)); } stream.close (); } }
도움이되기를 바랍니다.
면책 조항 : 나는 Minio에서 일합니다