Gostaria de verificar se existe uma chave em um determinado intervalo usando Java. Eu olhei para a API, mas não há métodos úteis. Tentei usar, getObject
mas gerou uma exceção.
java
amazon-web-services
amazon-s3
aws-sdk
em seus passos
fonte
fonte
Respostas:
Use a biblioteca jets3t. É muito mais fácil e robusto do que o SDK da AWS. Usando esta biblioteca você pode chamar, s3service.getObjectDetails (). Isso verificará e recuperará apenas os detalhes do objeto (não o conteúdo) do objeto. Ele lançará um 404 se o objeto estiver faltando. Portanto, você pode capturar essa exceção e lidar com ela em seu aplicativo.
Mas para que isso funcione, você precisará ter acesso ListBucket para o usuário nesse intervalo. O acesso apenas GetObject não funcionará. O motivo é que a Amazon o impedirá de verificar a presença da chave se você não tiver acesso a ListBucket. Apenas saber se uma chave está presente ou não, também será suficiente para usuários mal-intencionados em alguns casos. Portanto, a menos que eles tenham acesso a ListBucket, eles não poderão fazer isso.
fonte
Agora existe um método doesObjectExist na API Java oficial.
Aproveitar!
fonte
doesObjectExist
do SDK 2.x (atualmente v2.3.9).Atualizar:
Parece que há uma nova API para verificar exatamente isso. Veja outra resposta nesta página: https://stackoverflow.com/a/36653034/435605
Postagem original:
Usar
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); }
Observação sobre a exceção: eu sei que as exceções não devem ser usadas para controle de fluxo. O problema é que a Amazon não forneceu nenhuma API para verificar esse fluxo - apenas documentação sobre a exceção.
fonte
errorMessage
está definido como "Não encontrado", maserrorCode
é nulo.NoSuchKey
. Para obter uma lista definitiva dos códigos de erro S3, consulte a documentação: docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.htmlUsando o SDK da AWS, use o método getObjectMetadata. O método lançará uma AmazonServiceException se a chave não existir.
private AmazonS3 s3; ... public boolean exists(String path, String name) { try { s3.getObjectMetadata(bucket, getS3Path(path) + name); } catch(AmazonServiceException e) { return false; } return true; }
fonte
No Amazon Java SDK 1.10+, você pode usar
getStatusCode()
para obter o código de status da resposta HTTP, que será 404 se o objeto não existir.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()
consome menos recursos e a resposta não precisa ser fechada comogetObject()
.Nas versões anteriores, você pode usar
getErrorCode()
e verificar a string apropriada (depende da versão).fonte
Use o prefixo de configuração ListObjectsRequest como sua chave.
Código .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; } } }.
fonte
Para PHP (eu sei que a questão é Java, mas o Google me trouxe aqui), você pode usar stream wrappers e file_exists
$bucket = "MyBucket"; $key = "MyKey"; $s3 = Aws\S3\S3Client->factory([...]); $s3->registerStreamWrapper(); $keyExists = file_exists("s3://$bucket/$key");
fonte
Este código java verifica se a chave (arquivo) existe no intervalo 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; }
fonte
Divida seu caminho em balde e objeto. Testando o balde usando o método
doesBucketExist
, Testando o objeto usando o tamanho da listagem (0 caso não exista). Portanto, este código fará:String bucket = ...; String objectInBucket = ...; AmazonS3 s3 = new AmazonS3Client(...); return s3.doesBucketExist(bucket) && !s3.listObjects(bucket, objectInBucket).getObjectSummaries().isEmpty();
fonte
Usando Object isting. Função Java para verificar se a chave especificada existe no 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; }
fonte
Existe uma maneira fácil de fazer isso usando o método isObjectInBucket () da API jetS3t.
Código de amostra:
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 }
fonte
As outras respostas são para AWS SDK v1. Aqui está um método para AWS SDK v2 (atualmente 2.3.9).
Observe que os métodos
getObjectMetadata
edoesObjectExist
não estão atualmente no SDK v2! Portanto, essas não são mais opções. Somos forçados a usargetObject
oulistObjects
.listObjects
as chamadas são atualmente 12,5 vezes mais caras do que fazergetObject
. Mas a AWS também cobra por quaisquer dados baixados, o que aumenta o preçogetObject
se o arquivo existir . Contanto que seja muito improvável que o arquivo exista (por exemplo, você gerou uma nova chave UUID aleatoriamente e só precisa verificar se ela não foi usada), então chamargetObject
é significativamente mais barato pelos meus cálculos.Porém, apenas para garantir a segurança, adicionei uma
range()
especificação para solicitar que a AWS envie apenas alguns bytes do arquivo. Pelo que eu sei, o SDK sempre respeitará isso e não cobrará pelo download de todo o arquivo. Mas eu não verifiquei isso, então confie nesse comportamento por sua própria conta e risco! (Além disso, não tenho certeza de comorange
se comporta se o objeto S3 tiver 0 bytes de comprimento.)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; } }
Nota: este código assume
s3Client
elog
é declarado e inicializado em outro lugar. O método retorna um booleano, mas pode lançar exceções.fonte
s3Client.headObject()
na V2 para fazer isso: stackoverflow.com/a/56949742/9814131 , e você verificará oS3Exception
código de status 404 para verificar se o objeto existe de acordo com o problema do github github.com/aws/aws-sdk- java-v2 / issues / 297 . Mas eu acho que o seu é mais progressivo, pois tem tão pouca sobrecarga quanto 0-3 bytes.A maneira certa de fazer isso no SDK V2, sem a sobrecarga de realmente obter o objeto, é usar S3Client.headObject . Apoiado oficialmente pelo AWS Change Log .
fonte
Eu também enfrentei esse problema quando usei
String BaseFolder = "3patti_Logs"; S3Object object = s3client.getObject(bucketName, BaseFolder);
Recebi a chave de erro não encontrada
Quando eu bato e tento
String BaseFolder = "3patti_Logs"; S3Object object = s3client.getObject(bucketName, BaseFolder+"/");
funcionou, este código está funcionando com jar 1.9, caso contrário, atualize para 1.11 e use doesObjectExist como dito acima
fonte
Como outros mencionaram, para o AWS S3 Java SDK 2.10+ você pode usar o objeto HeadObjectRequest para verificar se há um arquivo em seu balde S3. Isso funcionará como uma solicitação GET sem realmente obter o arquivo.
Código de exemplo, já que outros não adicionaram nenhum código acima:
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; } }
fonte
headObjectResponse
nada.throws Exception
não é necessário também.Alternativamente, você pode usar a biblioteca cliente Minio-Java , seu código aberto e compatível com AWS S3 API.
Você pode usar exemplos Minio-Java StatObject.java para o mesmo.
Espero que ajude.
Disclaimer: Eu trabalho para Minio
fonte