我想检查使用Java在给定存储桶中是否存在密钥。我查看了API,但没有任何方法有用。我尝试使用getObject
,但它抛出异常。
答案 0 :(得分:225)
现在官方Java API中有doesObjectExist方法。
享受!
答案 1 :(得分:55)
使用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来检查这个流程 - 只是关于异常的文档。
答案 2 :(得分: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;
}
答案 3 :(得分:11)
在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();
S3Object 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()
并检查相应的字符串(取决于版本)。
答案 4 :(得分:6)
使用jets3t库。它比AWS sdk更容易和更强大。使用此库可以调用s3service.getObjectDetails()。这将仅检查和检索对象的对象(而不是内容)的详细信息。如果对象丢失,它将抛出404。因此,您可以捕获该异常并在您的应用中处理它。
但为了使其正常工作,您需要为该存储桶上的用户提供ListBucket访问权限。只是GetObject访问将无法正常工作。原因是,如果您没有ListBucket访问权限,亚马逊将阻止您检查是否存在密钥。在某些情况下,仅知道密钥是否存在,对于恶意用户也是足够的。因此,除非他们有ListBucket访问权限,否则他们将无法访问。
答案 5 :(得分: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;
}
}
}.
答案 6 :(得分:5)
对于PHP(我知道问题是Java,但谷歌把我带到这里),你可以使用流包装器和file_exists
$bucket = "MyBucket";
$key = "MyKey";
$s3 = Aws\S3\S3Client->factory([...]);
$s3->registerStreamWrapper();
$keyExists = file_exists("s3://$bucket/$key");
答案 7 :(得分: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;
}
答案 8 :(得分:3)
使用Object isting。用于检查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;
}
答案 9 :(得分:2)
将你的路径分解为桶和对象。
使用doesBucketExist
方法测试存储桶,
使用列表的大小测试对象(如果不存在则为0)。
所以这段代码会做:
String bucket = ...;
String objectInBucket = ...;
AmazonS3 s3 = new AmazonS3Client(...);
return s3.doesBucketExist(bucket)
&& !s3.listObjects(bucket, objectInBucket).getObjectSummaries().isEmpty();
答案 10 :(得分: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
}
答案 11 :(得分:1)
就像其他人提到的那样,对于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;
}
}
答案 12 :(得分: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
答案 13 :(得分:0)
或者,您可以使用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
工作答案 14 :(得分:0)
其他答案适用于AWS开发工具包v1。这是适用于AWS开发工具包v2(当前为2.3.9)的方法。
请注意,v2 SDK当前没有getObjectMetadata
和doesObjectExist
方法!因此,这些不再是选择。我们被迫使用getObject
或listObjects
。
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;
}
}
注意:此代码假定s3Client
和log
在其他地方声明和初始化。方法返回一个布尔值,但可以引发异常。
答案 15 :(得分:0)
在SDK V2中执行此操作的正确方法,而不会导致实际获取对象的负担, 是使用S3Client.headObject。 由AWS Change Log官方支持。