如何使用 Java 检查给定 S3 存储桶中是否存在指定密钥

发布于 2024-12-18 14:11:28 字数 76 浏览 0 评论 0原文

我想使用 Java 检查给定存储桶中是否存在密钥。我查看了 API,但没有任何有用的方法。我尝试使用 getObject 但它引发了异常。

I would like to check if a key exists in a given bucket using Java. I looked at the API but there aren't any methods that are useful. I tried to use getObject but it threw an exception.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

十年不长 2024-12-25 14:11:28

现在有一个 doesObjectExist 官方Java API中的方法。

享受!

编辑:这仅适用于适用于 Java 1.x 的 AWS 开发工具包。

There's now a doesObjectExist method in the official Java API.

Enjoy!

EDIT: This works only in AWS SDK for Java 1.x.

别忘他 2024-12-25 14:11:28

更新:

似乎有一个新的 API 可以检查这一点。请参阅本页中的另一个答案: https://stackoverflow.com/a/36653034/435605

原始帖子:

使用 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);
}

关于异常的注意事项:我知道异常不应该用于流量控制。问题是 Amazon 没有提供任何 api 来检查此流程 - 只是有关异常的文档。

Update:

It seems there's a new API to check just that. See another answer in this page: https://stackoverflow.com/a/36653034/435605

Original post:

Use 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);
}

Note about the exception: I know exceptions should not be used for flow control. The problem is that Amazon didn't provide any api to check this flow - just documentation about the exception.

假扮的天使 2024-12-25 14:11:28

AWS SDK for Java 2.x 的更新

在 SDK V2 中执行此操作的正确方法是使用 S3Client.headObject()
由 [4.1.1. 中的 AWS 变更日志] 正式支持。 S3 操作迁移][2] 部分。

示例代码:

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;
    }
}

有关 HeadObject 操作的更多信息可以在官方文档中找到: HeadObject

Update for the AWS SDK for Java 2.x

The right way to do it in SDK V2, without the overload of actually getting the object, is to use S3Client.headObject().
Officially backed by AWS Change Log in the [4.1.1. S3 Operation Migration][2] section.

Example code:

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;
    }
}

More info about the HeadObject operation can be found in the official documentation: HeadObject.

2024-12-25 14:11:28

使用 AWS 开发工具包使用 getObjectMetadata 方法。如果密钥不存在,该方法将抛出 AmazonServiceException。

private AmazonS3 s3;
...
public boolean exists(String path, String name) {
    try {
        s3.getObjectMetadata(bucket, getS3Path(path) + name); 
    } catch(AmazonServiceException e) {
        return false;
    }
    return true;
}

Using the AWS SDK use the getObjectMetadata method. The method will throw an AmazonServiceException if the key doesn't exist.

private AmazonS3 s3;
...
public boolean exists(String path, String name) {
    try {
        s3.getObjectMetadata(bucket, getS3Path(path) + name); 
    } catch(AmazonServiceException e) {
        return false;
    }
    return true;
}
物价感观 2024-12-25 14:11:28

在 Amazon Java SDK 1.10+ 中,您可以使用 getStatusCode() 获取HTTP响应的状态码,如果对象不存在则为404。

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() 消耗的资源更少,并且不需要像 getObject() 那样关闭响应。


在以前的版本中,您可以使用 getErrorCode() 并检查适当的字符串(取决于版本)。

In Amazon Java SDK 1.10+, you can use getStatusCode() to get the status code of the HTTP response, which will be 404 if the object does not exist.

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() consumes fewer resources, and the response doesn't need to be closed like getObject().


In previous versions, you can use getErrorCode() and check for the appropriate string (depends on the version).

花之痕靓丽 2024-12-25 14:11:28

使用 ListObjectsRequest 设置 Prefix 作为密钥。

.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;
            }
        }
    }.

Use ListObjectsRequest setting Prefix as your key.

.NET code:

 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;
            }
        }
    }.
半葬歌 2024-12-25 14:11:28

对于 PHP(我知道问题是 Java,但 Google 把我带到这里),您可以使用流包装器和 file_exists

$bucket = "MyBucket";
$key = "MyKey";
$s3 = Aws\S3\S3Client->factory([...]);
$s3->registerStreamWrapper();
$keyExists = file_exists("s3://$bucket/$key");

For PHP (I know the question is Java, but Google brought me here), you can use stream wrappers and file_exists

$bucket = "MyBucket";
$key = "MyKey";
$s3 = Aws\S3\S3Client->factory([...]);
$s3->registerStreamWrapper();
$keyExists = file_exists("s3://$bucket/$key");
葬シ愛 2024-12-25 14:11:28

此 java 代码检查 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;
}

This java code checks if the key (file) exists in s3 bucket.

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;
}
烟织青萝梦 2024-12-25 14:11:28

正如其他人提到的,对于 AWS S3 Java SDK 2.10+,您可以使用 HeadObjectRequest 对象来检查您的 S3 存储桶中是否有文件。这就像 GET 请求一样,但实际上并没有获取文件。

示例代码,因为其他人实际上没有在上面添加任何代码:

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;
   }
}

As others have mentioned, for the AWS S3 Java SDK 2.10+ you can use the HeadObjectRequest object to check if there is a file in your S3 bucket. This will act like a GET request without actually getting the file.

Example code since others haven't actually added any code above:

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;
   }
}
仅一夜美梦 2024-12-25 14:11:28

将您的路径分成桶和对象。
使用方法 doesBucketExist 测试存储桶,
使用列表的大小测试对象(如果不存在则为 0)。
所以这段代码将执行以下操作:

String bucket = ...;
String objectInBucket = ...;
AmazonS3 s3 = new AmazonS3Client(...);
return s3.doesBucketExist(bucket) 
       && !s3.listObjects(bucket, objectInBucket).getObjectSummaries().isEmpty();

Break your path into bucket and object.
Testing the bucket using the method doesBucketExist,
Testing the object using the size of the listing (0 in case not exist).
So this code will do:

String bucket = ...;
String objectInBucket = ...;
AmazonS3 s3 = new AmazonS3Client(...);
return s3.doesBucketExist(bucket) 
       && !s3.listObjects(bucket, objectInBucket).getObjectSummaries().isEmpty();
中二柚 2024-12-25 14:11:28

其他答案适用于 AWS SDK v1。以下是 AWS SDK v2(当前为 2.3.9)的方法。

请注意,v2 SDK 目前不包含 getObjectMetadatadoesObjectExist 方法!所以这些不再是选择。我们被迫使用 getObjectlistObjects

目前,listObjects 调用的成本是 getObject 的 12.5 倍。但 AWS 还会对下载的任何数据收费,这会提高 getObject 如果文件存在 的价格。只要该文件不太可能存在(例如,您随机生成了一个新的 UUID 密钥,只需仔细检查它是否未被占用),那么调用 getObject 的成本要低得多我的计算。

不过,为了安全起见,我添加了 range() 规范,要求 AWS 仅发送文件的几个字节。据我所知,SDK 将始终尊重这一点,并且不会向您收取下载整个文件的费用。但我还没有验证这一点,所以依赖这种行为需要您自担风险! (另外,我不确定如果 S3 对象的长度为 0 字节,range 的行为如何。)

    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;
    }
}

注意:此代码假设 s3Clientlog > 在别处声明和初始化。方法返回一个布尔值,但可以抛出异常。

The other answers are for AWS SDK v1. Here is a method for AWS SDK v2 (currently 2.3.9).

Note that getObjectMetadata and doesObjectExist methods are not currently in the v2 SDK! So those are no longer options. We are forced to use either getObject or listObjects.

listObjects calls are currently 12.5 times more expensive to make than getObject. But AWS also charges for any data downloaded, which raises the price of getObject if the file exists. As long as the file is very unlikely to exist (for example, you have generated a new UUID key randomly and just need to double-check that it isn't taken) then calling getObject is significantly cheaper by my calculation.

Just to be on the safe side though, I added a range() specification to ask AWS to only send a few bytes of the file. As far as I know the SDK will always respect this and not charge you for downloading the whole file. But I haven't verified that so rely on that behavior at your own risk! (Also, I'm not sure what how range behaves if the S3 object is 0 bytes long.)

    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;
    }
}

Note: this code assumes s3Client and log are declared and initialized elsewhere. Method returns a boolean, but can throw exceptions.

海之角 2024-12-25 14:11:28

使用对象列表。用于检查 AWS S3 中是否存在指定密钥的 Java 函数。

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;
    }

Using Object isting. Java function to check if specified key exist in 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;
    }
宫墨修音 2024-12-25 14:11:28

有一种简单的方法可以使用 jetS3t API 的 isObjectInBucket() 方法来完成此操作。

示例代码:

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

        }

There is an easy way to do it using jetS3t API's isObjectInBucket() method.

Sample 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

        }
孤蝉 2024-12-25 14:11:28

我也遇到这个问题
当我使用时,

String BaseFolder = "3patti_Logs"; 
S3Object object = s3client.getObject(bucketName, BaseFolder);
 

我得到错误密钥未找到

当我点击并尝试

String BaseFolder = "3patti_Logs"; 
S3Object object = s3client.getObject(bucketName, BaseFolder+"/");

它工作时,此代码适用于 1.9 jar,否则更新到 1.11 并使用 doesObjectExist 如上所述

I also faced this problem
when I used

String BaseFolder = "3patti_Logs"; 
S3Object object = s3client.getObject(bucketName, BaseFolder);
 

I got error key not found

When I hit and try

String BaseFolder = "3patti_Logs"; 
S3Object object = s3client.getObject(bucketName, BaseFolder+"/");

it worked , this code is working with 1.9 jar otherwise update to 1.11 and use doesObjectExist as said above

空名 2024-12-25 14:11:28

使用 jets3t 库。它比 AWS sdk 更简单、更强大。使用此库,您可以调用 s3service.getObjectDetails()。这将仅检查和检索对象的详细信息(而不是对象的内容)。如果对象丢失,它将抛出 404。因此,您可以捕获该异常并在您的应用程序中处理它。

但为了使其发挥作用,您需要拥有该存储桶上的用户的 ListBucket 访问权限。仅 GetObject 访问是行不通的。原因是,如果您没有 ListBucket 访问权限,亚马逊将阻止您检查密钥是否存在。在某些情况下,只要知道密钥是否存在,对于恶意用户来说就足够了。因此,除非他们具有 ListBucket 访问权限,否则他们将无法这样做。

Use the jets3t library. Its a lot more easier and robust than the AWS sdk. Using this library you can call, s3service.getObjectDetails(). This will check and retrieve only the details of the object (not the contents) of the object. It will throw a 404 if the object is missing. So you can catch that exception and deal with it in your app.

But in order for this to work, you will need to have ListBucket access for the user on that bucket. Just GetObject access will not work. The reason being, Amazon will prevent you from checking for the presence of the key if you dont have ListBucket access. Just knowing whether a key is present or not, will also suffice for malicious users in some cases. Hence unless they have ListBucket access they will not be able to do so.

燃情 2024-12-25 14:11:28

也许这会起作用?

    /**
 * Exist object
 *
 * @param bucketName - Bucket name
 * @param key        - Object key
 * @return Mono<Boolean>
 */
public Mono<Boolean> existObject(String bucketName, String key) {
    return Mono.fromFuture(client.headObject(HeadObjectRequest.builder().key(key).bucket(bucketName).build()))
            .flatMap(result -> Mono.just(true))
            .onErrorResume(error -> Mono.just(false));
}

Maybe this will work ?

    /**
 * Exist object
 *
 * @param bucketName - Bucket name
 * @param key        - Object key
 * @return Mono<Boolean>
 */
public Mono<Boolean> existObject(String bucketName, String key) {
    return Mono.fromFuture(client.headObject(HeadObjectRequest.builder().key(key).bucket(bucketName).build()))
            .flatMap(result -> Mono.just(true))
            .onErrorResume(error -> Mono.just(false));
}
若水般的淡然安静女子 2024-12-25 14:11:28

或者,您可以使用 Minio-Java 客户端库,它是开源的并且与 AWS S3 API 兼容。

您可以使用 Minio-Java StatObject.java 示例对于同样的。

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)
    throws NoSuchAlgorithmException, IOException, InvalidKeyException, XmlPullParserException, MinioException {
    // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are
    // dummy values, please replace them with original values.
    // Set s3 endpoint, region is calculated automatically
    MinioClient s3Client = new MinioClient("https://s3.amazonaws.com", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY");
    InputStream stream = s3Client.getObject("my-bucketname", "my-objectname");

    byte[] buf = new byte[16384];
    int bytesRead;
    while ((bytesRead = stream.read(buf, 0, buf.length)) >= 0) {
      System.out.println(new String(buf, 0, bytesRead));
    }

    stream.close();
  }
}

我希望它有帮助。

免责声明:我为 Minio 工作

Alternatively you can use Minio-Java client library, its Open Source and compatible with AWS S3 API.

You can use Minio-Java StatObject.java examples for the same.

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)
    throws NoSuchAlgorithmException, IOException, InvalidKeyException, XmlPullParserException, MinioException {
    // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are
    // dummy values, please replace them with original values.
    // Set s3 endpoint, region is calculated automatically
    MinioClient s3Client = new MinioClient("https://s3.amazonaws.com", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY");
    InputStream stream = s3Client.getObject("my-bucketname", "my-objectname");

    byte[] buf = new byte[16384];
    int bytesRead;
    while ((bytesRead = stream.read(buf, 0, buf.length)) >= 0) {
      System.out.println(new String(buf, 0, bytesRead));
    }

    stream.close();
  }
}

I hope it helps.

Disclaimer : I work for Minio

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文