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.
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.
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ć.
W oficjalnym interfejsie API języka Java jest teraz metoda doObjectExist .
Cieszyć się!
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.
errorMessage
jest ustawiony na „Nie znaleziono”, ale errorCode
jest pusty.
NoSuchKey
. Ostateczną listę kodów błędów S3 można znaleźć w dokumentacji: docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
Korzystają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;
}
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 jak getObject()
.
W poprzednich wersjach można użyć getErrorCode()
i sprawdzić odpowiedni ciąg (w zależności od wersji).
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;
}
}
}.
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");
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;
}
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();
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;
}
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;
}
}
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
}
Pozostałe odpowiedzi dotyczą AWS SDK v1. Oto metoda dla AWS SDK v2 (obecnie 2.3.9).
Zwróć uwagę, że metody getObjectMetadata
i doesObjectExist
nie są obecnie dostępne w zestawie SDK w wersji 2! Więc to nie są już opcje. Jesteśmy zmuszeni użyć albo getObject
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
i log
jest zadeklarowany i zainicjowany w innym miejscu. Metoda zwraca wartość logiczną, ale może zgłaszać wyjątki.
s3Client.headObject()
w V2 do zrobienia tego: stackoverflow.com/a/56949742/9814131 , a sprawdzisz S3Exception
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
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;
}
}
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.
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) rzuca NoSuchAlgorithmException, IOException, InvalidKeyException, XmlPullParserException, MinioException { // Uwaga: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY i my-bucketname to // wartości fikcyjne, zastąp je oryginalnymi wartościami. // Ustaw punkt końcowy s3, region jest obliczany automatycznie MinioClient s3Client = nowy MinioClient („https://s3.amazonaws.com”, „TWÓJ-KLUCZ DOSTĘPU”, „TWÓJ-SEKRETAKCESKLUCZ”); InputStream stream = s3Client.getObject ("my-bucketname", "my-objectname"); bajt [] buf = nowy bajt [16384]; int bytesRead; while ((bytesRead = stream.read (buf, 0, buf.length))> = 0) { System.out.println (new String (buf, 0, bytesRead)); } stream.close (); } }
Mam nadzieję, że to pomoże.
Zastrzeżenie: pracuję dla Minio