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

in *_*eps 74 java amazon-s3 amazon-web-services aws-sdk

我想检查使用Java在给定存储桶中是否存在密钥.我查看了API,但没有任何方法有用.我试图使用,getObject但它抛出异常.

mal*_*ana 246

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

请享用!

  • 它在1.10.51中添加 (9认同)
  • 知道如何使用 2.x SDK 实现这一点吗? (7认同)
  • 我们必须赞成这一点,并把它带到顶端! (4认同)
  • 这必须进行网络调用,如果你有很多对象,这是很昂贵的...太糟糕了,它不能只在元数据请求上返回null. (4认同)
  • 正确的做法是将其作为公认的答案,但只有OP可以做到这一点.http://meta.stackexchange.com/questions/120568/is-it-possible-to-change-the-chosen-answer (2认同)
  • 看起来亚马逊从2.x SDK(当前为v2.3.9)中删除了“ doesObjectExist”。 (2认同)

Ali*_*aka 56

使用 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);
}
Run Code Online (Sandbox Code Playgroud)

关于异常的注意事项:我知道异常不应该用于流控制.问题是亚马逊没有提供任何api来检查这个流程 - 只是关于异常的文档.

  • @SimonPeck:你是对的.问题是亚马逊没有提供任何api来检查这个流程 - 只是关于异常的文档.如果不进行投票,请删除您的投票. (29认同)
  • 不要将异常处理用于程序控制. (13认同)
  • 我会去寻找状态代码404.看起来比查看字符串更强大 (3认同)
  • @rboarman的评论不正确 - 它是'NoSuchKey`.有关S3错误代码的最终列表,请参阅文档:http://docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html (2认同)

use*_*051 21

使用AWS SDK使用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;
}
Run Code Online (Sandbox Code Playgroud)

  • @SimonPeck,它并不理想,但是当亚马逊提供适当的exists()方法时,你的观点是有效的. (15认同)
  • 不要将异常处理用于程序控制. (5认同)
  • @ AlikElzin-kilaka,因为getObject()意味着你必须下载对象的内容,这可能是巨大的. (4认同)
  • @SimonPeck你在这种情况下有另一种选择吗?这并非公然滥用例外作为程序控制流程......这样做简单,准确,安全.如果你把你的想法发挥到极致(显然你是因为你认为这段代码片段滥用异常),那么为什么语言中会有例外?而不是抛出异常**来警告程序并改变程序的流程**,运行时应该终止我想. (3认同)
  • getObject也会抛出AmazonServiceException,为什么要进行两次调用呢?另外,我如何知道该重复对象不存在?也许是因为另一个S3错误并确实找到了对象. (2认同)

Pau*_*per 12

在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;
    }
}
Run Code Online (Sandbox Code Playgroud)

getObjectMetadata()消耗更少的资源,响应不需要像关闭一样getObject().


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


小智 11

在 SDK V2 中执行此操作的正确方法是使用S3Client.headObject,而无需实际获取对象的过载。由AWS Change Log正式支持。

示例代码:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)


set*_*thu 5

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

但是,要使其正常工作,您将需要对该存储桶上的用户具有ListBucket访问权限。仅GetObject访问将不起作用。原因是,如果您没有ListBucket访问权限,Amazon将阻止您检查密钥是否存在。在某些情况下,仅知道密钥是否存在就足以满足恶意用户的需要。因此,除非他们具有ListBucket访问权限,否则他们将无法访问。

  • 全部-在下面查看此问题的更新答案:http://stackoverflow.com/a/36653034/49678 (3认同)
  • jets3t是一个旧的已弃用的库。而是使用aws-java-sdk。 (2认同)

use*_*402 5

使用ListObjectsRequest设置前缀作为您的密钥.

.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;
            }
        }
    }.
Run Code Online (Sandbox Code Playgroud)

  • 警告!亚马逊为每个LIST电话收取额外费用!这个方法没问题,但在下载之前不要用它来检查文件是否存在. (6认同)

Ric*_*mer 5

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

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