Tôi muốn kiểm tra xem khóa có tồn tại trong một nhóm nhất định bằng Java hay không. Tôi đã xem xét API nhưng không có bất kỳ phương pháp nào hữu ích. Tôi đã cố gắng sử dụng getObject
nhưng nó đã ném ra một ngoại lệ.
Tôi muốn kiểm tra xem khóa có tồn tại trong một nhóm nhất định bằng Java hay không. Tôi đã xem xét API nhưng không có bất kỳ phương pháp nào hữu ích. Tôi đã cố gắng sử dụng getObject
nhưng nó đã ném ra một ngoại lệ.
Câu trả lời:
Sử dụng thư viện jets3t. Nó dễ dàng và mạnh mẽ hơn rất nhiều so với AWS sdk. Sử dụng thư viện này, bạn có thể gọi, s3service.getObjectDetails (). Thao tác này sẽ chỉ kiểm tra và truy xuất các chi tiết của đối tượng (không phải nội dung) của đối tượng. Nó sẽ ném 404 nếu đối tượng bị thiếu. Vì vậy, bạn có thể nắm bắt ngoại lệ đó và giải quyết nó trong ứng dụng của mình.
Nhưng để điều này hoạt động, bạn sẽ cần có quyền truy cập ListBucket cho người dùng trên nhóm đó. Chỉ cần truy cập GetObject sẽ không hoạt động. Lý do là Amazon sẽ ngăn bạn kiểm tra sự hiện diện của khóa nếu bạn không có quyền truy cập ListBucket. Chỉ cần biết liệu có khóa hay không, cũng sẽ đủ cho những người dùng độc hại trong một số trường hợp. Do đó, trừ khi họ có quyền truy cập ListBucket, họ sẽ không thể làm như vậy.
Hiện có một phương thức doesObjectExist trong API Java chính thức.
Thưởng thức!
doesObjectExist
khỏi SDK 2.x (hiện tại là v2.3.9).
Cập nhật:
Có vẻ như có một API mới để kiểm tra điều đó. Xem câu trả lời khác trong trang này: https://stackoverflow.com/a/36653034/435605
Bài gốc:
Sử dụng 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);
}
Lưu ý về ngoại lệ: Tôi biết ngoại lệ không nên được sử dụng để kiểm soát luồng. Vấn đề là Amazon không cung cấp bất kỳ api nào để kiểm tra luồng này - chỉ là tài liệu về ngoại lệ.
errorMessage
được đặt thành "Không tìm thấy", nhưng errorCode
giá trị là rỗng.
NoSuchKey
. Để có danh sách chính xác về mã lỗi S3, hãy xem tài liệu: docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
Sử dụng AWS SDK, hãy sử dụng phương thức getObjectMetadata. Phương thức sẽ ném một AmazonServiceException nếu khóa không tồn tại.
private AmazonS3 s3;
...
public boolean exists(String path, String name) {
try {
s3.getObjectMetadata(bucket, getS3Path(path) + name);
} catch(AmazonServiceException e) {
return false;
}
return true;
}
Trong Amazon Java SDK 1.10+, bạn có thể sử dụng getStatusCode()
để lấy mã trạng thái của phản hồi HTTP, mã này sẽ là 404 nếu đối tượng không tồn tại.
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()
tiêu thụ ít tài nguyên hơn và phản hồi không cần phải đóng như vậy getObject()
.
Trong các phiên bản trước, bạn có thể sử dụng getErrorCode()
và kiểm tra chuỗi phù hợp (tùy thuộc vào phiên bản).
Sử dụng Tiền tố cài đặt ListObjectsRequest làm khóa của bạn.
Mã .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;
}
}
}.
Đối với PHP (tôi biết câu hỏi là Java, nhưng Google đã đưa tôi đến đây), bạn có thể sử dụng trình bao bọc luồng và file_exists
$bucket = "MyBucket";
$key = "MyKey";
$s3 = Aws\S3\S3Client->factory([...]);
$s3->registerStreamWrapper();
$keyExists = file_exists("s3://$bucket/$key");
Mã java này kiểm tra xem khóa (tệp) có tồn tại trong thùng s3 hay không.
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;
}
Chia đường dẫn của bạn thành thùng và đối tượng. Kiểm tra nhóm bằng phương pháp doesBucketExist
, Kiểm tra đối tượng bằng cách sử dụng kích thước của danh sách (0 trong trường hợp không tồn tại). Vì vậy, mã này sẽ làm:
String bucket = ...;
String objectInBucket = ...;
AmazonS3 s3 = new AmazonS3Client(...);
return s3.doesBucketExist(bucket)
&& !s3.listObjects(bucket, objectInBucket).getObjectSummaries().isEmpty();
Sử dụng Object isting. Hàm Java để kiểm tra xem khóa được chỉ định có tồn tại trong AWS S3 hay không.
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;
}
Có một cách dễ dàng để làm điều đó bằng cách sử dụng phương thức isObjectInBucket () của API jetS3t.
Mã mẫu:
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
}
Các câu trả lời khác dành cho AWS SDK v1. Đây là một phương pháp cho AWS SDK v2 (hiện tại là 2.3.9).
Lưu ý rằng getObjectMetadata
và doesObjectExist
các phương thức hiện không có trong SDK v2! Vì vậy, đó không còn là lựa chọn nữa. Chúng tôi buộc phải sử dụng một trong hai getObject
hoặc listObjects
.
listObjects
Các cuộc gọi hiện đang đắt hơn 12,5 lần so với getObject
. Nhưng AWS cũng tính phí cho bất kỳ dữ liệu nào được tải xuống, điều này làm tăng giá getObject
nếu tệp tồn tại . Miễn là tệp rất khó tồn tại (ví dụ: bạn đã tạo một khóa UUID mới một cách ngẫu nhiên và chỉ cần kiểm tra kỹ xem nó không được sử dụng hay không) thì getObject
tính toán của tôi sẽ rẻ hơn đáng kể.
Tuy nhiên, để an toàn, tôi đã thêm một range()
thông số kỹ thuật để yêu cầu AWS chỉ gửi một vài byte tệp. Theo như tôi biết, SDK sẽ luôn tôn trọng điều này và không tính phí bạn tải xuống toàn bộ tệp. Nhưng tôi chưa xác minh điều đó vì vậy hãy dựa vào hành vi đó với rủi ro của riêng bạn! (Ngoài ra, tôi không chắc range
sẽ hoạt động như thế nào nếu đối tượng S3 dài 0 byte.)
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;
}
}
Lưu ý: mã này giả định s3Client
và log
được khai báo và khởi tạo ở nơi khác. Phương thức trả về một boolean, nhưng có thể ném các ngoại lệ.
s3Client.headObject()
trong V2 để thực hiện việc này: stackoverflow.com/a/56949742/9814131 và bạn sẽ kiểm tra S3Exception
mã trạng thái của 404 để kiểm tra xem đối tượng có tồn tại theo vấn đề github github.com/aws/aws-sdk- java-v2 / issue / 297 . Nhưng tôi đoán của bạn tiến bộ hơn vì nó có rất ít chi phí là 0-3 byte.
Cách thích hợp để thực hiện điều đó trong SDK V2, mà không bị quá tải khi thực sự nhận được đối tượng, là sử dụng S3Client.headObject . Được hỗ trợ chính thức bởi Nhật ký thay đổi AWS .
Tôi cũng gặp phải vấn đề này khi sử dụng
String BaseFolder = "3patti_Logs";
S3Object object = s3client.getObject(bucketName, BaseFolder);
Tôi không tìm thấy khóa báo lỗi
Khi tôi nhấn và thử
String BaseFolder = "3patti_Logs";
S3Object object = s3client.getObject(bucketName, BaseFolder+"/");
nó đã hoạt động, mã này đang hoạt động với jar 1.9 nếu không, hãy cập nhật lên 1.11 và sử dụng doesObjectExist như đã nói ở trên
Như những người khác đã đề cập, đối với AWS S3 Java SDK 2.10+, bạn có thể sử dụng đối tượng HeadObjectRequest để kiểm tra xem có tệp trong nhóm S3 của bạn hay không. Điều này sẽ hoạt động giống như một yêu cầu GET mà không thực sự nhận được tệp.
Mã mẫu vì những người khác chưa thực sự thêm bất kỳ mã nào ở trên:
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
ở tất cả. throws Exception
cũng không cần thiết.
Ngoài ra, bạn có thể sử dụng thư viện máy khách Minio-Java , Mã nguồn mở của nó và tương thích với API AWS S3.
Bạn có thể sử dụng các ví dụ Minio-Java StatObject.java tương tự.
nhập io.minio.MinioClient; nhập io.minio.errors.MinioException; nhập java.io.InputStream; nhập java.io.IOException; nhập java.security.NoSuchAlgorithmException; nhập java.security.InvalidKeyException; nhập org.xmlpull.v1.XmlPullParserException; lớp công khai GetObject { public static void main (String [] args) ném NoSuchAlgorithmException, IOException, InvalidKeyException, XmlPullParserException, MinioException { // Lưu ý: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY và my-bucketname là // giá trị giả, vui lòng thay thế chúng bằng giá trị gốc. // Đặt điểm cuối s3, vùng được tính toán tự động MinioClient s3Client = new MinioClient ("https://s3.amazonaws.com", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY"); InputStream stream = s3Client.getObject ("my-bucketname", "my-objectname"); byte [] buf = byte mới [16384]; int bytesRead; while ((bytesRead = stream.read (buf, 0, buf.length))> = 0) { System.out.println (Chuỗi mới (buf, 0, bytesRead)); } stream.close (); } }
Tôi hy vọng nó sẽ giúp.
Tuyên bố từ chối trách nhiệm: Tôi làm việc cho Minio