Je voudrais vérifier si une clé existe dans un seau donné en utilisant Java. J'ai regardé l'API mais aucune méthode n'est utile. J'ai essayé d'utiliser getObject
mais cela a jeté une exception.
Je voudrais vérifier si une clé existe dans un seau donné en utilisant Java. J'ai regardé l'API mais aucune méthode n'est utile. J'ai essayé d'utiliser getObject
mais cela a jeté une exception.
Réponses:
Utilisez la bibliothèque jets3t. C'est beaucoup plus facile et robuste que le sdk AWS. En utilisant cette bibliothèque, vous pouvez appeler s3service.getObjectDetails (). Cela vérifiera et ne récupérera que les détails de l'objet (pas le contenu) de l'objet. Il lancera un 404 si l'objet est manquant. Vous pouvez donc intercepter cette exception et la gérer dans votre application.
Mais pour que cela fonctionne, vous devez disposer d'un accès ListBucket pour l'utilisateur sur ce compartiment. L'accès à GetObject ne fonctionnera pas. La raison en est qu'Amazon vous empêchera de vérifier la présence de la clé si vous n'avez pas accès à ListBucket. Le simple fait de savoir si une clé est présente ou non suffira également aux utilisateurs malveillants dans certains cas. Par conséquent, à moins d'avoir accès à ListBucket, ils ne pourront pas le faire.
Il existe maintenant une méthode doesObjectExist dans l'API Java officielle.
Prendre plaisir!
doesObjectExist
du SDK 2.x (actuellement v2.3.9).
Mise à jour:
Il semble qu'il existe une nouvelle API pour vérifier cela. Voir une autre réponse dans cette page: https://stackoverflow.com/a/36653034/435605
Message d'origine:
Utilisation 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);
}
Remarque sur l'exception: je sais que les exceptions ne doivent pas être utilisées pour le contrôle de flux. Le problème est qu'Amazon n'a fourni aucune API pour vérifier ce flux - juste de la documentation sur l'exception.
errorMessage
est défini sur "Not Found", mais le errorCode
est nul.
NoSuchKey
. Pour une liste définitive des codes d'erreur S3, consultez la documentation: docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
À l'aide du kit SDK AWS, utilisez la méthode getObjectMetadata. La méthode lèvera une AmazonServiceException si la clé n'existe pas.
private AmazonS3 s3;
...
public boolean exists(String path, String name) {
try {
s3.getObjectMetadata(bucket, getS3Path(path) + name);
} catch(AmazonServiceException e) {
return false;
}
return true;
}
Dans Amazon Java SDK 1.10+, vous pouvez utiliser getStatusCode()
pour obtenir le code d'état de la réponse HTTP, qui sera 404 si l'objet n'existe pas.
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()
consomme moins de ressources et la réponse n'a pas besoin d'être fermée comme getObject()
.
Dans les versions précédentes, vous pouvez utiliser getErrorCode()
et vérifier la chaîne appropriée (dépend de la version).
Utilisez ListObjectsRequest setting Prefix comme clé.
Code .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;
}
}
}.
Pour PHP (je sais que la question est Java, mais Google m'a amené ici), vous pouvez utiliser des wrappers de flux et file_exists
$bucket = "MyBucket";
$key = "MyKey";
$s3 = Aws\S3\S3Client->factory([...]);
$s3->registerStreamWrapper();
$keyExists = file_exists("s3://$bucket/$key");
Ce code java vérifie si la clé (fichier) existe dans le compartiment 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;
}
Divisez votre chemin en seau et objet. Test du bucket à l'aide de la méthode doesBucketExist
, Test de l'objet à l'aide de la taille de la liste (0 en cas d'existence) Donc, ce code fera:
String bucket = ...;
String objectInBucket = ...;
AmazonS3 s3 = new AmazonS3Client(...);
return s3.doesBucketExist(bucket)
&& !s3.listObjects(bucket, objectInBucket).getObjectSummaries().isEmpty();
Utiliser Object isting. Fonction Java pour vérifier si la clé spécifiée existe dans 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;
}
Il existe un moyen simple de le faire en utilisant la méthode isObjectInBucket () de l'API jetS3t.
Exemple de code:
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
}
Les autres réponses concernent AWS SDK v1. Voici une méthode pour AWS SDK v2 (actuellement 2.3.9).
Notez que les méthodes getObjectMetadata
et doesObjectExist
ne sont pas actuellement dans le SDK v2! Ce ne sont donc plus des options. Nous sommes obligés d'utiliser soit getObject
ou listObjects
.
listObjects
les appels sont actuellement 12,5 fois plus chers à faire que getObject
. Mais AWS facture également toutes les données téléchargées, ce qui augmente le prix de getObject
l'existence du fichier . Tant qu'il est très peu probable que le fichier existe (par exemple, vous avez généré une nouvelle clé UUID de manière aléatoire et devez simplement vérifier qu'elle n'est pas prise), puis appelezgetObject
est nettement moins cher selon mon calcul.
Par souci de sécurité, j'ai ajouté une range()
spécification demandant à AWS de n'envoyer que quelques octets du fichier. Autant que je sache, le SDK respectera toujours cela et ne vous facturera pas pour le téléchargement du fichier entier. Mais je n'ai pas vérifié cela, alors comptez sur ce comportement à vos risques et périls! (De plus, je ne sais pas comment range
se comporte si l'objet S3 a une longueur de 0 octet.)
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;
}
}
Remarque: ce code suppose s3Client
et log
est déclaré et initialisé ailleurs. La méthode renvoie un booléen, mais peut lever des exceptions.
s3Client.headObject()
dans V2 pour faire ceci: stackoverflow.com/a/56949742/9814131 , et vous vérifierez le S3Exception
code de statut 404 pour vérifier si l'objet existe selon le problème github github.com/aws/aws-sdk- java-v2 / issues / 297 . Mais je suppose que le vôtre est plus progressif car il a aussi très peu de frais généraux que 0-3 octets.
La bonne façon de le faire dans SDK V2, sans la surcharge liée à l'obtention de l'objet, est d'utiliser S3Client.headObject . Officiellement soutenu par AWS Change Log .
J'ai également rencontré ce problème lorsque j'utilisais
String BaseFolder = "3patti_Logs";
S3Object object = s3client.getObject(bucketName, BaseFolder);
J'ai la clé d'erreur introuvable
Quand je frappe et essaie
String BaseFolder = "3patti_Logs";
S3Object object = s3client.getObject(bucketName, BaseFolder+"/");
cela a fonctionné, ce code fonctionne avec 1.9 jar sinon mettez à jour à 1.11 et utilisez doObjectExist comme indiqué ci-dessus
Comme d'autres l'ont mentionné, pour AWS S3 Java SDK 2.10+, vous pouvez utiliser l' objet HeadObjectRequest pour vérifier s'il existe un fichier dans votre compartiment S3. Cela agira comme une requête GET sans obtenir le fichier.
Exemple de code puisque les autres n'ont en fait ajouté aucun code ci-dessus:
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
n'est pas nécessaire non plus.
Vous pouvez également utiliser la bibliothèque cliente Minio-Java , son Open Source et compatible avec l'API AWS S3.
Vous pouvez utiliser des exemples Minio-Java StatObject.java pour le même.
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; classe publique GetObject { public static void main (String [] args) jette NoSuchAlgorithmException, IOException, InvalidKeyException, XmlPullParserException, MinioException { // Remarque: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY et my-bucketname sont // valeurs factices, veuillez les remplacer par les valeurs d'origine. // Définit le point de terminaison s3, la région est calculée automatiquement MinioClient s3Client = new MinioClient ("https://s3.amazonaws.com", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY"); InputStream stream = s3Client.getObject ("my-bucketname", "my-objectname"); byte [] buf = nouvel octet [16384]; int bytesRead; while ((bytesRead = stream.read (buf, 0, buf.length))> = 0) { System.out.println (nouvelle chaîne (buf, 0, bytesRead)); } stream.close (); } }
J'espère que cela aide.
Clause de non-responsabilité: je travaille pour Minio