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.
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.
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.
Agora existe um método doesObjectExist na API Java oficial.
Aproveitar!
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.
errorMessage
está definido como "Não encontrado", mas errorCode
é 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.html
Usando 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;
}
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 como getObject()
.
Nas versões anteriores, você pode usar getErrorCode()
e verificar a string apropriada (depende da versão).
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;
}
}
}.
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");
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;
}
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();
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;
}
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
}
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
e doesObjectExist
não estão atualmente no SDK v2! Portanto, essas não são mais opções. Somos forçados a usar getObject
ou listObjects
.
listObjects
as chamadas são atualmente 12,5 vezes mais caras do que fazer getObject
. Mas a AWS também cobra por quaisquer dados baixados, o que aumenta o preço getObject
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 chamar getObject
é 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 como range
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
e log
é declarado e inicializado em outro lugar. O método retorna um booleano, mas pode lançar exceções.
s3Client.headObject()
na V2 para fazer isso: stackoverflow.com/a/56949742/9814131 , e você verificará o S3Exception
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 .
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
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;
}
}
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.
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) lança NoSuchAlgorithmException, IOException, InvalidKeyException, XmlPullParserException, MinioException { // Observação: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY e my-bucketname são // valores fictícios, substitua-os pelos valores originais. // Definir endpoint s3, região é calculada automaticamente MinioClient s3Client = new MinioClient ("https://s3.amazonaws.com", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY"); InputStream stream = s3Client.getObject ("my-bucketname", "my-objectname"); byte [] buf = novo byte [16384]; int bytesRead; while ((bytesRead = stream.read (buf, 0, buf.length))> = 0) { System.out.println (nova String (buf, 0, bytesRead)); } stream.close (); } }
Espero que ajude.
Disclaimer: Eu trabalho para Minio