Я хотів би перевірити, чи існує ключ у даному сегменті за допомогою Java. Я подивився API, але немає жодних корисних методів. Я намагався використати, getObject
але це призвело до винятку.
Я хотів би перевірити, чи існує ключ у даному сегменті за допомогою Java. Я подивився API, але немає жодних корисних методів. Я намагався використати, getObject
але це призвело до винятку.
Відповіді:
Скористайтеся бібліотекою jets3t. Це набагато простіше і надійніше, ніж AWS sdk. За допомогою цієї бібліотеки ви можете зателефонувати, s3service.getObjectDetails (). Це дозволить перевірити та отримати лише деталі об’єкта (а не вміст) об’єкта. Якщо об'єкт відсутній, він викине 404. Тож ви можете вловити цей виняток і впоратися з ним у своєму додатку.
Але для того, щоб це працювало, вам потрібно мати доступ до ListBucket для користувача в цьому сегменті. Просто доступ до GetObject не буде працювати. Причина в тому, що Amazon не дозволить вам перевірити наявність ключа, якщо у вас немає доступу до ListBucket. Одного лише знання того, чи є ключ чи ні, в деяких випадках також буде достатньо для зловмисних користувачів. Отже, якщо вони не мають доступу до ListBucket, вони не зможуть цього зробити.
Зараз в офіційному API Java є метод doObjectExist .
Насолоджуйтесь!
doesObjectExist
з SDK 2.x (на даний момент 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);
}
Примітка щодо винятку: Я знаю, що винятки не повинні використовуватися для контролю потоку. Проблема в тому, що Amazon не надав жодного API для перевірки цього потоку - лише документація про виняток.
errorMessage
встановлено значення "Не знайдено", але значення errorCode
є нулем.
NoSuchKey
. Остаточний перелік кодів помилок S3 див. У документації: docs.aws.amazon.com/AmazonS3/latest/API/ErrorResponses.html
Використовуючи 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;
}
У 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.
.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;
}
}
}.
Для PHP (я знаю, що питання в Java, але Google привів мене сюди), ви можете використовувати обгортки потоків і file_exists
$bucket = "MyBucket";
$key = "MyKey";
$s3 = Aws\S3\S3Client->factory([...]);
$s3->registerStreamWrapper();
$keyExists = file_exists("s3://$bucket/$key");
Цей код 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();
Використання Object isting. Функція 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;
}
Існує простий спосіб зробити це, використовуючи метод isObjectInBucket () API jetS3t.
Зразок коду:
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 SDK v1. Ось метод для AWS SDK v2 (на даний момент 2.3.9).
Зверніть увагу, що getObjectMetadata
і doesObjectExist
методів наразі немає у v2 SDK! Тож це вже не варіанти. Ми змушені використовувати 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
код стану 404, щоб перевірити, чи існує об’єкт відповідно до випуску github github.com/aws/aws-sdk- java-v2 / issues / 297 . Але я думаю, ваші є більш прогресивними, оскільки вони мають настільки мало накладних витрат, як 0-3 байти.
Правильним способом зробити це в SDK V2, без перевантаження фактично отримання об’єкта, є використання S3Client.headObject . Офіційно підкріплено журналом змін AWS .
Я також стикався з цією проблемою, коли використовував
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, як зазначено вище
Як вже згадували інші, для 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 , її Open Source і сумісну з 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 { public static 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 stream = s3Client.getObject ("my-bucketname", "my-objectname"); байт [] buf = новий байт [16384]; int bytesRead; while ((bytesRead = stream.read (buf, 0, buf.length))> = 0) { System.out.println (новий рядок (buf, 0, bytesRead)); } stream.close (); } }
Сподіваюся, це допоможе.
Застереження: я працюю на Minio