Chciałbym sprawdzić, czy klucz istnieje w danym zasobniku za pomocą Javy. Przyjrzałem się API, ale nie ma żadnych przydatnych metod. Próbowałem użyć, getObject
ale rzuciło to wyjątek.
java
amazon-web-services
amazon-s3
aws-sdk
w Jego krokach
źródło
źródło
Odpowiedzi:
Skorzystaj z biblioteki jets3t. Jest o wiele prostszy i bardziej wytrzymały niż zestaw SDK AWS. Korzystając z tej biblioteki, możesz wywołać s3service.getObjectDetails (). Spowoduje to sprawdzenie i pobranie tylko szczegółów obiektu (nie zawartości) obiektu. Jeśli brakuje obiektu, wyrzuci 404. Możesz więc złapać ten wyjątek i zająć się nim w swojej aplikacji.
Ale aby to zadziałało, musisz mieć dostęp do ListBucket dla użytkownika w tym zasobniku. Sam dostęp do GetObject nie zadziała. Powodem jest to, że Amazon uniemożliwi sprawdzenie obecności klucza, jeśli nie masz dostępu do ListBucket. W niektórych przypadkach wystarczy wiedzieć, czy klucz jest obecny, czy nie. Dlatego jeśli nie mają dostępu do ListBucket, nie będą mogli tego zrobić.
źródło
W oficjalnym interfejsie API języka Java jest teraz metoda doObjectExist .
Cieszyć się!
źródło
doesObjectExist
z 2.x SDK (obecnie v2.3.9).Aktualizacja:
Wygląda na to, że istnieje nowe API, które to sprawdza. Zobacz inną odpowiedź na tej stronie: https://stackoverflow.com/a/36653034/435605
Oryginalny post:
Posługiwać się
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); }
Uwaga na temat wyjątku: wiem, że wyjątków nie należy używać do sterowania przepływem. Problem polega na tym, że Amazon nie dostarczył żadnego interfejsu API do sprawdzenia tego przepływu - tylko dokumentacja dotycząca wyjątku.
źródło
errorMessage
jest ustawiony na „Nie znaleziono”, aleerrorCode
jest pusty.NoSuchKey
. Ostateczną listę kodów błędów S3 można znaleźć w dokumentacji: docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.htmlKorzystając z AWS SDK, użyj metody getObjectMetadata. Metoda zgłosi wyjątek AmazonServiceException, jeśli klucz nie istnieje.
private AmazonS3 s3; ... public boolean exists(String path, String name) { try { s3.getObjectMetadata(bucket, getS3Path(path) + name); } catch(AmazonServiceException e) { return false; } return true; }
źródło
W Amazon Java SDK 1.10+ możesz użyć,
getStatusCode()
aby uzyskać kod stanu odpowiedzi HTTP, który będzie 404, jeśli obiekt nie istnieje.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()
zużywa mniej zasobów, a odpowiedź nie musi być zamykana jakgetObject()
.W poprzednich wersjach można użyć
getErrorCode()
i sprawdzić odpowiedni ciąg (w zależności od wersji).źródło
Użyj Prefiksu ustawienia ListObjectsRequest jako klucza.
Kod .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; } } }.
źródło
W przypadku PHP (wiem, że pytanie brzmi Java, ale Google mnie tu przywiodło) możesz użyć opakowań strumieniowych i file_exists
$bucket = "MyBucket"; $key = "MyKey"; $s3 = Aws\S3\S3Client->factory([...]); $s3->registerStreamWrapper(); $keyExists = file_exists("s3://$bucket/$key");
źródło
Ten kod java sprawdza, czy klucz (plik) istnieje w zasobniku 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; }
źródło
Przebij swoją ścieżkę do wiadra i przedmiotu. Testowanie zasobnika za pomocą metody
doesBucketExist
, Testowanie obiektu przy użyciu rozmiaru listy (0 w przypadku braku). Więc ten kod zrobi:String bucket = ...; String objectInBucket = ...; AmazonS3 s3 = new AmazonS3Client(...); return s3.doesBucketExist(bucket) && !s3.listObjects(bucket, objectInBucket).getObjectSummaries().isEmpty();
źródło
Korzystanie z Object isting. Funkcja Java do sprawdzania, czy określony klucz istnieje w AWS S3.
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; }
źródło
Właściwym sposobem na zrobienie tego w SDK V2, bez przeciążania faktycznego pobierania obiektu, jest użycie S3Client.headObject . Oficjalnie wspierane przez AWS Change Log .
Przykładowy kod:
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; } }
źródło
Można to łatwo zrobić za pomocą metody isObjectInBucket () interfejsu API jetS3t.
Przykładowy kod:
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 }
źródło
Pozostałe odpowiedzi dotyczą AWS SDK v1. Oto metoda dla AWS SDK v2 (obecnie 2.3.9).
Zwróć uwagę, że metody
getObjectMetadata
idoesObjectExist
nie są obecnie dostępne w zestawie SDK w wersji 2! Więc to nie są już opcje. Jesteśmy zmuszeni użyć albogetObject
lublistObjects
.listObjects
połączenia są obecnie 12,5 razy droższe niżgetObject
. Ale AWS pobiera również opłaty za pobrane dane, co podnosi cenę,getObject
jeśli plik istnieje . O ile jest bardzo mało prawdopodobne, że plik istnieje (na przykład wygenerowałeś losowo nowy klucz UUID i po prostu musisz dwukrotnie sprawdzić, czy nie jest zajęty), a następnie wywołaniegetObject
według moich obliczeń jest znacznie tańsze.Jednak
range()
na wszelki wypadek dodałem specyfikację, aby poprosić AWS o przesłanie tylko kilku bajtów pliku. O ile wiem, SDK zawsze to uszanuje i nie pobierze opłat za pobranie całego pliku. Ale nie zweryfikowałem tego, więc polegaj na tym zachowaniu na własne ryzyko! (Nie jestem też pewien, jak sięrange
zachowa, jeśli obiekt S3 ma długość 0 bajtów).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; } }
Uwaga: ten kod zakłada
s3Client
ilog
jest zadeklarowany i zainicjowany w innym miejscu. Metoda zwraca wartość logiczną, ale może zgłaszać wyjątki.źródło
s3Client.headObject()
w V2 do zrobienia tego: stackoverflow.com/a/56949742/9814131 , a sprawdziszS3Exception
kod stanu 404, aby sprawdzić, czy obiekt istnieje zgodnie z problemem github github.com/aws/aws-sdk- java-v2 / Issues / 297 . Ale wydaje mi się, że twój jest bardziej progresywny, ponieważ ma bardzo mały narzut, jak 0-3 bajtów.Miałem też ten problem, kiedy korzystałem
String BaseFolder = "3patti_Logs"; S3Object object = s3client.getObject(bucketName, BaseFolder);
Nie znaleziono klucza błędu
Kiedy uderzam i próbuję
String BaseFolder = "3patti_Logs"; S3Object object = s3client.getObject(bucketName, BaseFolder+"/");
zadziałało, ten kod działa z jar 1.9, w przeciwnym razie zaktualizuj do wersji 1.11 i użyj doObjectExist, jak wspomniano powyżej
źródło
Jak wspominali inni, w przypadku AWS S3 Java SDK 2.10+ możesz użyć HeadObjectRequest obiektu aby sprawdzić, czy S3 znajduje się plik. Będzie to działać jak żądanie GET bez faktycznego pobierania pliku.
Przykładowy kod, ponieważ inni faktycznie nie dodali żadnego kodu powyżej:
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; } }
źródło
headObjectResponse
.throws Exception
nie jest również potrzebne.Alternatywnie możesz użyć biblioteki klienckiej Minio-Java , jej Open Source i kompatybilnej z API AWS S3.
Możesz użyć przykładów Minio-Java StatObject.java do tego samego.
Mam nadzieję, że to pomoże.
Zastrzeżenie: pracuję dla Minio
źródło