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, getObjectmas 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, getObjectmas 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!
doesObjectExistdo 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.
errorMessageestá 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 getObjectMetadatae doesObjectExistnão estão atualmente no SDK v2! Portanto, essas não são mais opções. Somos forçados a usar getObjectou listObjects.
listObjectsas 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 rangese 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 s3Cliente 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 S3Exceptioncó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;
}
}
headObjectResponsenada. throws Exceptionnã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