Skip to content

Commit 6716eb7

Browse files
authored
Add S3Client listObjects support in S3Template (#831)
1 parent 14d910c commit 6716eb7

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

spring-cloud-aws-s3-parent/spring-cloud-aws-s3/src/main/java/io/awspring/cloud/s3/S3Operations.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.io.InputStream;
1919
import java.net.URL;
2020
import java.time.Duration;
21+
import java.util.List;
2122
import org.springframework.lang.Nullable;
2223
import software.amazon.awssdk.services.s3.S3Client;
2324
import software.amazon.awssdk.services.s3.model.CreateBucketResponse;
@@ -60,7 +61,17 @@ public interface S3Operations {
6061
* @param s3Url - the S3 url s3://bucket/key
6162
*/
6263
void deleteObject(String s3Url);
63-
64+
65+
/**
66+
* Returns some or all (up to 1,000) of the objects in a bucket.
67+
* Does not handle pagination. If you need pagination you should use {@link S3PathMatchingResourcePatternResolver} or {@link S3Client}
68+
*
69+
* @param bucketName - the bucket name
70+
* @param prefix - objects prefix
71+
* @return list of {@link S3Resource}
72+
*/
73+
List<S3Resource> listObjects(String bucketName, String prefix);
74+
6475
/**
6576
* Stores a Java object in a S3 bucket. Uses {@link S3ObjectConverter} for serialization.
6677
*

spring-cloud-aws-s3-parent/spring-cloud-aws-s3/src/main/java/io/awspring/cloud/s3/S3Template.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,16 @@
1919
import java.io.OutputStream;
2020
import java.net.URL;
2121
import java.time.Duration;
22+
import java.util.List;
23+
import java.util.stream.Collectors;
24+
2225
import org.springframework.lang.Nullable;
2326
import org.springframework.util.Assert;
2427
import org.springframework.util.StreamUtils;
2528
import software.amazon.awssdk.services.s3.S3Client;
2629
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
30+
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
31+
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
2732
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
2833
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
2934
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
@@ -84,7 +89,19 @@ public void deleteObject(String s3Url) {
8489
Location location = Location.of(s3Url);
8590
this.deleteObject(location.getBucket(), location.getObject());
8691
}
87-
92+
93+
@Override
94+
public List<S3Resource> listObjects(String bucketName, String prefix) {
95+
Assert.notNull(bucketName, "bucketName is required");
96+
Assert.notNull(prefix, "prefix is required");
97+
98+
final ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(bucketName).prefix(prefix).build();
99+
final ListObjectsV2Response response = s3Client.listObjectsV2(request);
100+
101+
return response.contents().stream()
102+
.map(s3Object -> new S3Resource(bucketName, s3Object.key(), s3Client, s3OutputStreamProvider)).toList();
103+
}
104+
88105
@Override
89106
public S3Resource store(String bucketName, String key, Object object) {
90107
Assert.notNull(bucketName, "bucketName is required");

spring-cloud-aws-s3-parent/spring-cloud-aws-s3/src/test/java/io/awspring/cloud/s3/S3TemplateIntegrationTests.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import java.net.URL;
2727
import java.nio.charset.StandardCharsets;
2828
import java.time.Duration;
29+
import java.util.List;
30+
2931
import org.apache.http.HttpEntity;
3032
import org.apache.http.HttpResponse;
3133
import org.apache.http.client.methods.HttpGet;
@@ -147,6 +149,20 @@ void deletesObjectByS3Url() {
147149
.isThrownBy(() -> client.headObject(r -> r.bucket(BUCKET_NAME).key("key.txt")));
148150
}
149151

152+
@Test
153+
void listObjects() throws IOException {
154+
client.putObject(r -> r.bucket(BUCKET_NAME).key("hello-en.txt"), RequestBody.fromString("hello"));
155+
client.putObject(r -> r.bucket(BUCKET_NAME).key("hello-fr.txt"), RequestBody.fromString("bonjour"));
156+
client.putObject(r -> r.bucket(BUCKET_NAME).key("bye.txt"), RequestBody.fromString("bye"));
157+
158+
List<S3Resource> resources = s3Template.listObjects(BUCKET_NAME, "hello");
159+
assertThat(resources.size()).isEqualTo(2);
160+
161+
// According to the S3Client doc : "Objects are returned sorted in an ascending order of the respective key names in the list."
162+
assertThat(resources).extracting(S3Resource::getInputStream).map(is -> new String(is.readAllBytes(), StandardCharsets.UTF_8))
163+
.containsExactly("hello", "bonjour");
164+
}
165+
150166
@Test
151167
void storesObject() throws IOException {
152168
S3Resource storedObject = s3Template.store(BUCKET_NAME, "person.json", new Person("John", "Doe"));

0 commit comments

Comments
 (0)