Удалить папку и ее содержимое 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;
}
}
}
В 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());
}
}