Я хотел бы проверить, существует ли ключ в данном ковше с использованием Java. Я посмотрел API, но нет полезных методов. Я попытался использовать getObject
, но он сделал исключение.
Как проверить, существует ли указанный ключ в данном ведре S3 с использованием Java
Ответ 1
Используйте библиотеку jets3t. Это намного проще и надежнее, чем AWS sdk. С помощью этой библиотеки вы можете вызвать s3service.getObjectDetails(). Это будет проверять и извлекать только детали объекта (а не содержимого) объекта. Он будет вызывать 404, если объект отсутствует. Таким образом, вы можете поймать это исключение и справиться с ним в своем приложении.
Но для того, чтобы это сработало, вам нужно будет иметь доступ к ListBucket для пользователя в этом ковше. Просто доступ к GetObject не будет работать. Причина в том, что Amazon не позволит вам проверить наличие ключа, если у вас нет доступа к ListBucket. В некоторых случаях будет достаточно знать, есть ли ключ или нет, для злоумышленников. Следовательно, если у них нет доступа к ListBucket, они не смогут этого сделать.
Ответ 2
Теперь в официальном Java API существует doesObjectExist.
Наслаждайтесь!
Ответ 3
Обновить:
Кажется, есть новый API, чтобы проверить это. Смотрите другой ответ на этой странице: 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 для проверки этого потока - просто документация об исключении.
Ответ 4
Используя 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;
}
Ответ 5
В 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()
и проверить соответствующую строку (в зависимости от версии).
Ответ 6
Используйте параметр 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;
}
}
}.
Ответ 7
Для PHP (я знаю, что вопрос - это Java, но Google привел меня сюда), вы можете использовать обертки потоков и файловые_эксты
$bucket = "MyBucket";
$key = "MyKey";
$s3 = Aws\S3\S3Client->factory([...]);
$s3->registerStreamWrapper();
$keyExists = file_exists("s3://$bucket/$key");
Ответ 8
Этот код 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;
}
Ответ 9
Разместите свой путь в ведро и объект.
Тестирование ведра с помощью метода doesBucketExist
,
Тестирование объекта с использованием размера листинга (0 в случае отсутствия).
Так что этот код будет делать:
String bucket = ...;
String objectInBucket = ...;
AmazonS3 s3 = new AmazonS3Client(...);
return s3.doesBucketExist(bucket)
&& !s3.listObjects(bucket, objectInBucket).getObjectSummaries().isEmpty();
Ответ 10
Использование 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;
}
Ответ 11
Существует простой способ сделать это с помощью метода 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
}
Ответ 12
В качестве альтернативы вы можете использовать Minio-Java, свой Open Source и совместимый с 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
Ответ 13
Использовать метод doBucketExist для S3Client в AWS SDK
static final AmazonS3 S3_CLIENT = AmazonS3ClientBuilder.defaultClient();
if (!S3_CLIENT.doesBucketExist(bucketName)) {
CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName, region);
Bucket bucket = S3_CLIENT.createBucket(createBucketRequest);
logger.log("Created Bucket Name" + bucket.getName() + " | Creation :" + bucket.getCreationDate());
}
Надеюсь, что это поможет.
Ответ 14
Другие ответы для AWS SDK v1. Вот метод для AWS SDK v2 (в настоящее время 2.3.9).
Обратите внимание, что getObjectMetadata
и doesObjectExist
в настоящее время отсутствуют в SDK v2! Так что это уже не варианты. Мы вынуждены использовать либо 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
объявлены и инициализированы в другом месте. Метод возвращает логическое значение, но может выдавать исключения.
Ответ 15
Правильный способ сделать это в SDK V2 без перегрузки фактического получения объекта - это использовать S3Client.headObject. Официально поддерживается AWS Change Log.