Saya ingin memeriksa apakah ada kunci dalam bucket tertentu menggunakan Java. Saya melihat API tetapi tidak ada metode yang berguna. Saya mencoba menggunakan getObject
tetapi itu membuat pengecualian.
Saya ingin memeriksa apakah ada kunci dalam bucket tertentu menggunakan Java. Saya melihat API tetapi tidak ada metode yang berguna. Saya mencoba menggunakan getObject
tetapi itu membuat pengecualian.
Jawaban:
Gunakan perpustakaan jets3t. Ini jauh lebih mudah dan kuat daripada sdk AWS. Menggunakan pustaka ini, Anda bisa memanggil, s3service.getObjectDetails (). Ini akan memeriksa dan mengambil hanya detail objek (bukan konten) objek. Ini akan melempar 404 jika objeknya hilang. Jadi Anda bisa menangkap pengecualian itu dan menanganinya di aplikasi Anda.
Tetapi agar ini berfungsi, Anda harus memiliki akses ListBucket untuk pengguna di keranjang itu. Akses GetObject saja tidak akan bekerja. Alasannya, Amazon akan mencegah Anda memeriksa keberadaan kunci jika Anda tidak memiliki akses ListBucket. Hanya mengetahui apakah kunci ada atau tidak, juga akan cukup untuk pengguna jahat dalam beberapa kasus. Karenanya, kecuali mereka memiliki akses ListBucket, mereka tidak akan dapat melakukannya.
Sekarang ada metode doesObjectExist di API Java resmi.
Nikmati!
doesObjectExist
dari 2.x SDK (saat ini v2.3.9).
Memperbarui:
Sepertinya ada API baru untuk memeriksa hal itu. Lihat jawaban lain di halaman ini: https://stackoverflow.com/a/36653034/435605
Posting asli:
Menggunakan 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);
}
Catatan tentang pengecualian: Saya tahu pengecualian tidak boleh digunakan untuk kontrol aliran. Masalahnya adalah Amazon tidak menyediakan api apa pun untuk memeriksa aliran ini - hanya dokumentasi tentang pengecualian.
errorMessage
disetel ke "Not Found", tetapi errorCode
null.
NoSuchKey
. Untuk daftar definitif kode kesalahan S3, lihat dokumentasi: docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
Menggunakan AWS SDK gunakan metode getObjectMetadata. Metode ini akan menampilkan AmazonServiceException jika kuncinya tidak ada.
private AmazonS3 s3;
...
public boolean exists(String path, String name) {
try {
s3.getObjectMetadata(bucket, getS3Path(path) + name);
} catch(AmazonServiceException e) {
return false;
}
return true;
}
Di Amazon Java SDK 1.10+, Anda dapat menggunakan getStatusCode()
untuk mendapatkan kode status respons HTTP, yaitu 404 jika objek tidak ada.
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()
mengkonsumsi lebih sedikit sumber daya, dan respons tidak perlu ditutup seperti getObject()
.
Di versi sebelumnya, Anda dapat menggunakan getErrorCode()
dan memeriksa string yang sesuai (tergantung versinya).
Gunakan ListObjectsRequest setting Prefix sebagai kunci Anda.
Kode .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;
}
}
}.
Untuk PHP (Saya tahu pertanyaannya adalah Java, tetapi Google membawa saya ke sini), Anda dapat menggunakan pembungkus aliran dan file_exists
$bucket = "MyBucket";
$key = "MyKey";
$s3 = Aws\S3\S3Client->factory([...]);
$s3->registerStreamWrapper();
$keyExists = file_exists("s3://$bucket/$key");
Kode java ini memeriksa apakah kunci (file) ada di bucket 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;
}
Hancurkan jalan Anda menjadi keranjang dan objek. Menguji keranjang menggunakan metode doesBucketExist
, Menguji objek menggunakan ukuran daftar (0 jika tidak ada). Jadi kode ini akan melakukan:
String bucket = ...;
String objectInBucket = ...;
AmazonS3 s3 = new AmazonS3Client(...);
return s3.doesBucketExist(bucket)
&& !s3.listObjects(bucket, objectInBucket).getObjectSummaries().isEmpty();
Menggunakan Object isting. Fungsi Java untuk memeriksa apakah kunci yang ditentukan ada di 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;
}
Cara yang tepat untuk melakukannya di SDK V2, tanpa kelebihan beban untuk benar-benar mendapatkan objek, adalah dengan menggunakan S3Client.headObject . Secara resmi didukung oleh AWS Change Log .
Kode contoh:
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;
}
}
Ada cara mudah untuk melakukannya menggunakan metode isObjectInBucket () jetS3t API.
Kode sampel:
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
}
Jawaban lainnya adalah untuk AWS SDK v1. Berikut adalah metode untuk AWS SDK v2 (saat ini 2.3.9).
Perhatikan bahwa getObjectMetadata
dan doesObjectExist
metode saat ini tidak ada di v2 SDK! Jadi itu bukan lagi pilihan. Kami terpaksa menggunakan salah satu getObject
atau listObjects
.
listObjects
panggilan saat ini 12,5 kali lebih mahal untuk dibuat daripada getObject
. Namun AWS juga mengenakan biaya untuk data apa pun yang diunduh, yang menaikkan harga getObject
jika file tersebut ada . Selama file tersebut sangat tidak mungkin ada (misalnya, Anda telah membuat kunci UUID baru secara acak dan hanya perlu memeriksa ulang bahwa itu tidak diambil) lalu memanggilgetObject
secara signifikan lebih murah menurut perhitungan saya.
Untuk berjaga-jaga, saya menambahkan range()
spesifikasi untuk meminta AWS hanya mengirim beberapa byte file. Sejauh yang saya tahu, SDK akan selalu menghormati ini dan tidak menagih Anda untuk mengunduh seluruh file. Tetapi saya belum memverifikasi bahwa jadi andalkan perilaku itu dengan risiko Anda sendiri! (Selain itu, saya tidak yakin bagaimana range
perilakunya jika objek S3 memiliki panjang 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;
}
}
Catatan: kode ini mengasumsikan s3Client
dan log
dideklarasikan serta diinisialisasi di tempat lain. Metode mengembalikan boolean, tetapi dapat memunculkan pengecualian.
s3Client.headObject()
di V2 untuk melakukan ini: stackoverflow.com/a/56949742/9814131 , dan Anda akan memeriksa S3Exception
kode status 404 untuk memeriksa apakah objek ada sesuai dengan masalah github github.com/aws/aws-sdk- java-v2 / issues / 297 . Tapi saya rasa milik Anda lebih progresif karena memiliki overhead yang sangat sedikit seperti 0-3 byte.
Saya juga menghadapi masalah ini saat saya menggunakannya
String BaseFolder = "3patti_Logs";
S3Object object = s3client.getObject(bucketName, BaseFolder);
Saya mendapat kunci kesalahan tidak ditemukan
Saat aku memukul dan mencoba
String BaseFolder = "3patti_Logs";
S3Object object = s3client.getObject(bucketName, BaseFolder+"/");
berhasil, kode ini bekerja dengan 1.9 jar jika tidak perbarui ke 1.11 dan gunakan doesObjectExist seperti yang dikatakan di atas
Seperti yang disebutkan orang lain, untuk AWS S3 Java SDK 2.10+ Anda dapat menggunakan objek HeadObjectRequest untuk memeriksa apakah ada file di bucket S3 Anda. Ini akan bertindak seperti permintaan GET tanpa benar-benar mendapatkan file tersebut.
Contoh kode karena orang lain belum benar-benar menambahkan kode apa pun di atas:
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
sama sekali. throws Exception
tidak dibutuhkan juga.
Atau Anda dapat menggunakan Minio-Java klien , Sumber Terbuka dan kompatibel dengan API AWS S3.
Anda dapat menggunakan Minio-Java StatObject.java contoh untuk hal yang sama.
impor io.minio.MinioClient; import io.minio.errors.MinioException; impor java.io.InputStream; impor java.io.IOException; impor java.security.NoSuchAlgorithmException; import java.security.InvalidKeyException; impor org.xmlpull.v1.XmlPullParserException; kelas publik GetObject { public static void main (String [] args) melempar NoSuchAlgorithmException, IOException, InvalidKeyException, XmlPullParserException, MinioException { // Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY, dan my-bucketname adalah // nilai dummy, harap ganti dengan nilai aslinya. // Tetapkan titik akhir s3, wilayah dihitung secara otomatis MinioClient s3Client = new MinioClient ("https://s3.amazonaws.com", "YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY"); Arus InputStream = s3Client.getObject ("nama-keranjang-saya", "nama-objek-saya"); byte [] buf = byte baru [16384]; int bytesRead; while ((bytesRead = stream.read (buf, 0, buf.length))> = 0) { System.out.println (String baru (buf, 0, bytesRead)); } stream.close (); } }
Saya harap ini membantu.
Penafian: Saya bekerja untuk Minio