我想使用Java检查给定存储桶中是否存在密钥。我看了看API,但没有任何有用的方法。我尝试使用,getObject
但是引发了异常。
Answers:
使用jets3t库。它比AWS sdk更轻松,更强大。使用此库,您可以调用s3service.getObjectDetails()。这将仅检查和检索对象的详细信息(而不是对象的内容)。如果缺少该对象,它将抛出404。因此,您可以捕获该异常并在您的应用程序中对其进行处理。
但是,要使其正常工作,您将需要对该存储桶上的用户具有ListBucket访问权限。仅GetObject访问将不起作用。原因是,如果您没有ListBucket访问权限,Amazon将阻止您检查密钥是否存在。在某些情况下,仅知道密钥是否存在也足以满足恶意用户的需要。因此,除非他们具有ListBucket访问权限,否则他们将无法访问。
官方Java API中现在有一个dosObjectExist方法。
请享用!
doesObjectExist
2.x SDK(当前为v2.3.9)中删除。
更新:
似乎有一个新的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来检查此流程-只是有关异常的文档。
errorMessage
的设置为“未找到”,但errorCode
为空。
使用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;
}
在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()
并检查适当的字符串(取决于版本)。
使用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;
}
}
}.
此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;
}
闯入桶和物体。使用方法测试存储桶,使用doesBucketExist
列表大小测试对象(如果不存在,则测试0)。因此,这段代码可以做到:
String bucket = ...;
String objectInBucket = ...;
AmazonS3 s3 = new AmazonS3Client(...);
return s3.doesBucketExist(bucket)
&& !s3.listObjects(bucket, objectInBucket).getObjectSummaries().isEmpty();
使用对象浪费。检查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;
}
使用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
}
其他答案适用于AWS开发工具包v1。这是适用于AWS开发工具包v2(当前为2.3.9)的方法。
请注意,v2 SDK当前没有getObjectMetadata
和doesObjectExist
方法!因此,这些不再是选择。我们被迫使用getObject
或listObjects
。
listObjects
目前,拨打电话的费用是的12.5倍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;
}
}
注意:此代码假定s3Client
并log
在其他地方声明和初始化。方法返回一个布尔值,但可以引发异常。
s3Client.headObject()
在V2中有一个要执行此操作:stackoverflow.com/a/56949742/9814131,您将S3Exception
根据github问题github.com/aws/aws-sdk-检查状态代码404以检查对象是否存在。java-v2 / issues / 297。但是我想您会更进步,因为它的开销只有0-3个字节。
在SDK V2中执行此操作的正确方法是使用S3Client.headObject,而不会导致实际获取该对象的负担。由AWS Change Log正式支持。
我使用时也遇到了这个问题
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
就像其他人提到的那样,对于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;
}
}
headObjectResponse
。throws Exception
也不需要。
或者,您可以使用Minio-Java客户端库,该客户端库是开源的并且与AWS S3 API兼容。
您可以使用Minio -Java StatObject.java示例。
导入io.minio.MinioClient; 导入io.minio.errors.MinioException; 导入java.io.InputStream; 导入java.io.IOException; 导入java.security.NoSuchAlgorithmException; 导入java.security.InvalidKeyException; 导入org.xmlpull.v1.XmlPullParserException; 公共类GetObject { 公共静态void main(String [] args) 引发NoSuchAlgorithmException,IOException,InvalidKeyException,XmlPullParserException,MinioException { //注意:YOUR-ACCESSKEYID,YOUR-SECRETACCESSKEY和my-bucketname是 //虚拟值,请用原始值替换它们。 //设置s3端点,区域会自动计算 MinioClient s3Client =新的MinioClient(“ https://s3.amazonaws.com”,“ YOUR-ACCESSKEYID”,“ YOUR-SECRETACCESSKEY”); InputStream流= s3Client.getObject(“ my-bucketname”,“ my-objectname”); byte [] buf =新的byte [16384]; int bytesRead; 而((bytesRead = stream.read(buf,0,buf.length))> = 0){ System.out.println(new String(buf,0,bytesRead)); } stream.close(); } }
希望对您有所帮助。
免责声明:我为Minio工作