Подтвердить что ты не робот

Как проверить, существует ли указанный ключ в данном ведре S3 с использованием Java

Я хотел бы проверить, существует ли ключ в данном ковше с использованием Java. Я посмотрел API, но нет полезных методов. Я попытался использовать getObject, но он сделал исключение.

4b9b3361

Ответ 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.