diff --git a/aws-modules/aws-reactive/pom.xml b/aws-modules/aws-reactive/pom.xml index 7a9cefb9d1..fbad5e30d0 100644 --- a/aws-modules/aws-reactive/pom.xml +++ b/aws-modules/aws-reactive/pom.xml @@ -91,7 +91,7 @@ 2.2.1.RELEASE - 2.10.27 + 2.17.283 \ No newline at end of file diff --git a/aws-modules/aws-reactive/src/main/java/com/baeldung/aws/reactive/s3/DownloadResource.java b/aws-modules/aws-reactive/src/main/java/com/baeldung/aws/reactive/s3/DownloadResource.java index 838ada1685..7793eeb079 100644 --- a/aws-modules/aws-reactive/src/main/java/com/baeldung/aws/reactive/s3/DownloadResource.java +++ b/aws-modules/aws-reactive/src/main/java/com/baeldung/aws/reactive/s3/DownloadResource.java @@ -3,17 +3,11 @@ */ package com.baeldung.aws.reactive.s3; -import java.io.InputStream; import java.nio.ByteBuffer; -import java.util.Map; import java.util.Map.Entry; -import java.util.concurrent.CompletableFuture; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; -import org.springframework.http.ResponseEntity.BodyBuilder; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -22,11 +16,7 @@ import org.springframework.web.bind.annotation.RestController; import lombok.extern.slf4j.Slf4j; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import software.amazon.awssdk.core.ResponseBytes; -import software.amazon.awssdk.core.SdkResponse; import software.amazon.awssdk.core.async.AsyncResponseTransformer; -import software.amazon.awssdk.core.async.SdkPublisher; -import software.amazon.awssdk.core.internal.async.ByteArrayAsyncResponseTransformer; import software.amazon.awssdk.http.SdkHttpResponse; import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.model.GetObjectRequest; @@ -40,38 +30,39 @@ import software.amazon.awssdk.services.s3.model.GetObjectResponse; @RequestMapping("/inbox") @Slf4j public class DownloadResource { - - + private final S3AsyncClient s3client; private final S3ClientConfigurarionProperties s3config; public DownloadResource(S3AsyncClient s3client, S3ClientConfigurarionProperties s3config) { this.s3client = s3client; - this.s3config = s3config; + this.s3config = s3config; } - - - @GetMapping(path="/{filekey}") - public Mono>> downloadFile(@PathVariable("filekey") String filekey) { - - GetObjectRequest request = GetObjectRequest.builder() - .bucket(s3config.getBucket()) - .key(filekey) - .build(); - - return Mono.fromFuture(s3client.getObject(request,new FluxResponseProvider())) - .map( (response) -> { - checkResult(response.sdkResponse); - String filename = getMetadataItem(response.sdkResponse,"filename",filekey); - log.info("[I65] filename={}, length={}",filename, response.sdkResponse.contentLength() ); - - return ResponseEntity.ok() - .header(HttpHeaders.CONTENT_TYPE, response.sdkResponse.contentType()) - .header(HttpHeaders.CONTENT_LENGTH, Long.toString(response.sdkResponse.contentLength())) - .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + filename + "\"") - .body(response.flux); - }); + @GetMapping(path = "/{filekey}") + public Mono>> downloadFile(@PathVariable("filekey") String filekey) { + + GetObjectRequest request = GetObjectRequest.builder() + .bucket(s3config.getBucket()) + .key(filekey) + .build(); + + return Mono.fromFuture(s3client.getObject(request, AsyncResponseTransformer.toPublisher())) + .map(response -> { + checkResult(response.response()); + String filename = getMetadataItem(response.response(), "filename", filekey); + + log.info("[I65] filename={}, length={}", filename, response.response() + .contentLength()); + + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_TYPE, response.response() + .contentType()) + .header(HttpHeaders.CONTENT_LENGTH, Long.toString(response.response() + .contentLength())) + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + filename + "\"") + .body(Flux.from(response)); + }); } /** @@ -82,63 +73,24 @@ public class DownloadResource { * @return */ private String getMetadataItem(GetObjectResponse sdkResponse, String key, String defaultValue) { - for( Entry entry : sdkResponse.metadata().entrySet()) { - if ( entry.getKey().equalsIgnoreCase(key)) { + for (Entry entry : sdkResponse.metadata() + .entrySet()) { + if (entry.getKey() + .equalsIgnoreCase(key)) { return entry.getValue(); } } return defaultValue; } - // Helper used to check return codes from an API call private static void checkResult(GetObjectResponse response) { SdkHttpResponse sdkResponse = response.sdkHttpResponse(); - if ( sdkResponse != null && sdkResponse.isSuccessful()) { + if (sdkResponse != null && sdkResponse.isSuccessful()) { return; } - + throw new DownloadFailedException(response); } - - - static class FluxResponseProvider implements AsyncResponseTransformer { - - private FluxResponse response; - - @Override - public CompletableFuture prepare() { - response = new FluxResponse(); - return response.cf; - } - - @Override - public void onResponse(GetObjectResponse sdkResponse) { - this.response.sdkResponse = sdkResponse; - } - - @Override - public void onStream(SdkPublisher publisher) { - response.flux = Flux.from(publisher); - response.cf.complete(response); - } - - @Override - public void exceptionOccurred(Throwable error) { - response.cf.completeExceptionally(error); - } - - } - - /** - * Holds the API response and stream - * @author Philippe - */ - static class FluxResponse { - - final CompletableFuture cf = new CompletableFuture<>(); - GetObjectResponse sdkResponse; - Flux flux; - } }