Удалить папку и ее содержимое AWS S3 java

Можно ли удалить папку (в корзине S3) и все ее содержимое с помощью одного запроса API, используя Java SDK для AWS. Для консоли браузера мы можем удалить и папку, и ее содержимое одним щелчком мыши, и я надеюсь, что такое же поведение должно быть доступно и с помощью API.

7 ответов

Решение

В S3 нет такой вещи как папки; Есть просто файлы с косой чертой в именах файлов.

Консоль браузера будет отображать эти слеши как папки, но они не настоящие.

Вы можете удалить все файлы с одинаковым префиксом, но сначала вам нужно найти их с помощью list_objects(), а затем вы можете удалить их в пакетном режиме.

Для фрагмента кода с использованием Java SDK, пожалуйста, обратитесь ниже документ

http://docs.aws.amazon.com/AmazonS3/latest/dev/DeletingMultipleObjectsUsingJava.html

Вы можете указать keyPrefix в ListObjectsRequest.

Например, рассмотрим корзину, которая содержит следующие ключи:

  • Foo / бар / Baz
  • Foo / бар / Баш
  • Foo / бар / челка
  • Foo / бух

И вы хотите удалить файлы из foo / bar / baz.

if (s3Client.doesBucketExist(bucketName)) {
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest()
                .withBucketName(bucketName)
                .withPrefix("foo/bar/baz");

        ObjectListing objectListing = s3Client.listObjects(listObjectsRequest);

        while (true) {
            for (S3ObjectSummary objectSummary : objectListing.getObjectSummaries()) {
                s3Client.deleteObject(bucketName, objectSummary.getKey());
            }
            if (objectListing.isTruncated()) {
                objectListing = s3Client.listNextBatchOfObjects(objectListing);
            } else {
                break;
            }
        }
    }

https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/model/ListObjectsRequest.html

В java sdk нет возможности указать имя папки или, более конкретно, префикс для удаления файлов. Но есть возможность указать массив ключей, которые вы хотите удалить. Щелкните для подробностей. Используя это, я написал небольшой метод для удаления всех файлов, соответствующих префиксу.

private AmazonS3 s3client = <Your s3 client>;
private String bucketName = <your bucket name, can be signed or unsigned>;

public void deleteDirectory(String prefix) {
    ObjectListing objectList = this.s3client.listObjects( this.bucketName, prefix );
    List<S3ObjectSummary> objectSummeryList =  objectList.getObjectSummaries();
    String[] keysList = new String[ objectSummeryList.size() ];
    int count = 0;
    for( S3ObjectSummary summery : objectSummeryList ) {
        keysList[count++] = summery.getKey();
    }
    DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest( bucketName ).withKeys( keysList );
    this.s3client.deleteObjects(deleteObjectsRequest);
}

Вы можете попробовать следующие методы, они справятся с удалением даже усеченных страниц, а также рекурсивно удалит все содержимое в данном каталоге:

         public Set<String> listS3DirFiles(String bucket, String dirPrefix) {
        ListObjectsV2Request s3FileReq = new ListObjectsV2Request()
                .withBucketName(bucket)
                .withPrefix(dirPrefix)
                .withDelimiter("/");

        Set<String> filesList = new HashSet<>();
        ListObjectsV2Result objectsListing;
        try {
            do {
                objectsListing = amazonS3.listObjectsV2(s3FileReq);
                objectsListing.getCommonPrefixes().forEach(folderPrefix -> {
                    filesList.add(folderPrefix);
                    Set<String> tempPrefix = listS3DirFiles(bucket, folderPrefix);
                    filesList.addAll(tempPrefix);
                });

                for (S3ObjectSummary summary: objectsListing.getObjectSummaries()) {
                    filesList.add(summary.getKey());
                }

                s3FileReq.setContinuationToken(objectsListing.getNextContinuationToken());
            } while(objectsListing.isTruncated());
        } catch (SdkClientException e) {
            System.out.println(e.getMessage());
            throw e;
        }

        return filesList;
    }

    public boolean deleteDirectoryContents(String bucket, String directoryPrefix) {
        Set<String> keysSet = listS3DirFiles(bucket, directoryPrefix);

        if (keysSet.isEmpty()) {
            System.out.println("Given directory {} doesn't have any file "+ directoryPrefix);
            return false;
        }

        DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(bucket)
                .withKeys(keysSet.toArray(new String[0]));
        try {
            amazonS3.deleteObjects(deleteObjectsRequest);
        }  catch (SdkClientException e) {
            System.out.println(e.getMessage());
            throw e;
        }

        return true;
    }

Сначала вам нужно получить все ключи объекта, начинающиеся с заданного префикса:

      public List<FileKey> list(String keyPrefix) {
  var objectListing = client.listObjects("bucket-name", keyPrefix);
  var paths =
      objectListing.getObjectSummaries().stream()
        .map(s3ObjectSummary -> s3ObjectSummary.getKey())
        .collect(Collectors.toList());

  while (objectListing.isTruncated()) {
    objectListing = client.listNextBatchOfObjects(objectListing);

    paths.addAll(
        objectListing.getObjectSummaries().stream()
            .map(s3ObjectSummary -> s3ObjectSummary.getKey())
            .toList());
  }

  return paths.stream().sorted().collect(Collectors.toList());
}

Затем вызовите deleteObjects:

      client.deleteObjects(new DeleteObjectsRequest("bucket-name").withKeys(list("some-prefix")));

Ответы здесь, похоже, используют более старую версию SDK.

Вот решение для Java SDKV2 AWS S3:

Оно используетListObjectsV2IterableотправлятьDeleteObjectsRequestв пределах 1000 ключей.

Также проверяется наличие пустого списка (возможен ответ от объектов списка, но не принимается объектами удаления).

        void deleteFolder(String bucket, String prefix) {
    ListObjectsV2Request listRequest =
        ListObjectsV2Request.builder()
            .bucket(bucket)
            .prefix(prefix)
            .build();
    ListObjectsV2Iterable paginatedListResponse = s3Client.listObjectsV2Paginator(listRequest);

    for (ListObjectsV2Response listResponse : paginatedListResponse) {
      List<ObjectIdentifier> objects =
          listResponse.contents().stream()
              .map(s3Object -> ObjectIdentifier.builder().key(s3Object.key()).build())
              .toList();
      if (objects.isEmpty()) {
        break;
      }
      DeleteObjectsRequest deleteRequest =
          DeleteObjectsRequest.builder()
              .bucket(bucket)
              .delete(Delete.builder().objects(objects).build())
              .build();
      s3Client.deleteObjects(deleteRequest);
    }
  }

Гдеs3Clientэто ваш экземплярS3Client.

Вы можете попробовать это

void deleteS3Folder(String bucketName, String folderPath) {
    for (S3ObjectSummary file : s3.listObjects(bucketName, folderPath).getObjectSummaries()){
        s3.deleteObject(bucketName, file.getKey());
    }
}
Другие вопросы по тегам