我想用 Java 检查给定的 bucket 中是否存在密钥。我查看了 API,但没有任何有用的方法。我尝试使用 getObject,但它抛出了一个异常。
getObject
使用 jets3t 库。它比 AWS sdk 简单和健壮得多。使用这个库,您可以调用 s3service.getObjectDetails ()。这将只检查和检索对象的详细信息(而不是内容)。如果物体丢失,它会抛出一个404。因此,您可以捕获这个异常并在应用程序中处理它。
但是为了让这个工作起作用,您需要让那个 bucket 上的用户访问 ListBucket。仅仅获取对象访问将不起作用。原因是,如果您没有 ListBucket 访问权限,Amazon 将阻止您检查密钥的存在。在某些情况下,只要知道密钥是否存在,对于恶意用户来说就足够了。因此,除非他们有 ListBucket 访问权限,否则他们将无法这样做。
使用 AWS SDK 使用 getObjectMetadata 方法。
private AmazonS3 s3; ... public boolean exists(String path, String name) { try { s3.getObjectMetadata(bucket, getS3Path(path) + name); } catch(AmazonServiceException e) { return false; } return true; }
更新:
似乎有一个新的 API 来检查这一点。请参阅本页的另一个答案: https://stackoverflow.com/a/36653034/435605
原文:
使用 errorCode.equals("NoSuchKey")
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 来检查这个流程,只是提供了关于异常的文档。
使用 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; } } }.
这段 java 代码检查键(文件)是否存在于 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; }
对于 PHP (我知道问题在于 Java,但是 Google 把我带到了这里) ,您可以使用流包装器和 file _ vis
$bucket = "MyBucket"; $key = "MyKey"; $s3 = Aws\S3\S3Client->factory([...]); $s3->registerStreamWrapper(); $keyExists = file_exists("s3://$bucket/$key");
有一种简单的方法可以使用 jetS3tAPI 的 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 }
在 Amazon Java SDK 1.10 + 中,可以使用 getStatusCode()获取 HTTP 响应的状态代码,如果对象不存在,则状态代码为404。
getStatusCode()
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()那样被关闭。
getObjectMetadata()
getObject()
在以前的版本中,可以使用 getErrorCode()并检查适当的字符串(取决于版本)。
getErrorCode()
把你的路分成水桶和物体。 采用 doesBucketExist方法对水桶进行测试, 使用清单的大小测试对象(如果不存在,则为0)。 所以这个代码可以:
doesBucketExist
String bucket = ...; String objectInBucket = ...; AmazonS3 s3 = new AmazonS3Client(...); return s3.doesBucketExist(bucket) && !s3.listObjects(bucket, objectInBucket).getObjectSummaries().isEmpty();
使用 Object listing.Java 函数检查 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; }
现在在官方 JavaAPI 中有一个 DoesObjectExist方法。
好好享受吧!
或者,您可以使用 小爪哇客户端库、其开放源码和兼容 AWS S3 API。
您可以使用 Minio-JavaStatObject.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(); } }
I hope it helps.
免责声明: 我为 米尼奥工作
下面是 AWS SDK v2(目前为2.3.9)的一个方法。
请注意,getObjectMetadata和 doesObjectExist方法目前不在 v2 SDK 中!所以这些都不再是选择了。我们被迫使用 getObject或 listObjects。
getObjectMetadata
doesObjectExist
listObjects
目前,listObjects呼叫的成本是 getObject的12.5倍。但是 AWS 也对下载的任何数据收费,这就提高了 getObject文件是否存在的价格。只要该文件不太可能存在(例如,您随机生成了一个新的 UUID 密钥,只需要再次检查它是否被使用) ,那么根据我的计算,调用 getObject的成本就会显著降低。
为了安全起见,我添加了一个 range()规范,要求 AWS 只发送几个字节的文件。据我所知,SDK 将始终尊重这一点,并不收取您下载整个文件。但我还没有证实这一点,所以依赖于你自己的风险行为!(另外,如果 S3对象的长度为0字节,我不确定 range的行为如何。)
range()
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; } }
注意: 此代码假设在其他地方声明并初始化了 s3Client和 log。方法返回一个布尔值,但是可以抛出异常。
s3Client
log
The right way to do it in SDK V2, without the overload of actually getting the object, 就是使用 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; } }
正如其他人提到的,对于 AWS S3 Java SDK 2.10 + ,您可以使用 头部目标请求对象来检查您的 S3 bucket 中是否有文件。这将作为一个 GET 请求,而不实际获取文件。
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; } }
我也遇到了这个问题 当我吸毒的时候
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 如上所述