108

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

4

16 回答 16

332

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

享受!

于 2016-04-15T17:06:45.537 回答
60

更新:

似乎有一个新的 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);
}

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

于 2013-04-04T09:46:10.100 回答
25

使用 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;
}
于 2013-01-29T16:03:38.627 回答
19

在 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()并检查适当的字符串(取决于版本)。

于 2015-08-04T17:50:05.023 回答
19

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

示例代码:

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;
    }
}
于 2019-05-08T10:14:51.037 回答
5

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

$bucket = "MyBucket";
$key = "MyKey";
$s3 = Aws\S3\S3Client->factory([...]);
$s3->registerStreamWrapper();
$keyExists = file_exists("s3://$bucket/$key");
于 2014-07-16T21:00:50.953 回答
5

使用 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;
            }
        }
    }.
于 2013-05-16T14:05:23.993 回答
4

此 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;
}
于 2013-05-23T15:55:50.130 回答
3

将您的路径分成存储桶和对象。使用方法测试bucket doesBucketExist,使用listing的大小测试对象(0表示不存在)。所以这段代码会做:

String bucket = ...;
String objectInBucket = ...;
AmazonS3 s3 = new AmazonS3Client(...);
return s3.doesBucketExist(bucket) 
       && !s3.listObjects(bucket, objectInBucket).getObjectSummaries().isEmpty();
于 2015-12-17T20:01:34.317 回答
3

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

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

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

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

    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在其他地方声明和初始化。方法返回一个布尔值,但可以抛出异常。

于 2019-02-02T00:47:16.573 回答
2

正如其他人所提到的,对于 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;
   }
}
于 2020-02-25T14:38:41.993 回答
2

使用对象列表。用于检查 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;
    }
于 2015-12-24T05:35:47.833 回答
1

使用 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

        }
于 2015-05-28T04:14:10.563 回答
1

我在使用的时候也遇到了这个问题

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 并使用 dosObjectExist,如上所述

于 2020-07-16T06:51:07.697 回答
0

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

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

于 2011-11-29T01:28:20.313 回答
-1

或者,您可以使用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工作

于 2016-05-13T14:39:09.320 回答