AWS code-library documentation change
Summary
Added complete Java code examples demonstrating stream uploads using AWS CRT-based S3 client, multipart-enabled async client, and Transfer Manager. Includes proper resource cleanup and executor management.
Security assessment
The changes focus on improving code examples for stream upload functionality with proper async handling and resource management. There is no mention of security vulnerabilities, patches, or security-specific configurations. The changes demonstrate standard best practices for async I/O operations but don't introduce or document security features.
Diff
diff --git a/code-library/latest/ug/s3_example_s3_Scenario_UploadStream_section.md b/code-library/latest/ug/s3_example_s3_Scenario_UploadStream_section.md index 794425661..cb2172f56 100644 --- a//code-library/latest/ug/s3_example_s3_Scenario_UploadStream_section.md +++ b//code-library/latest/ug/s3_example_s3_Scenario_UploadStream_section.md @@ -28 +27,0 @@ Use the [AWS CRT-based S3 Client](https://docs.aws.amazon.com/sdk-for-java/lates - import software.amazon.awssdk.core.async.BlockingInputStreamAsyncRequestBody; @@ -33,0 +33 @@ Use the [AWS CRT-based S3 Client](https://docs.aws.amazon.com/sdk-for-java/lates + import java.io.InputStream; @@ -35,0 +36,24 @@ Use the [AWS CRT-based S3 Client](https://docs.aws.amazon.com/sdk-for-java/lates + import java.util.concurrent.ExecutorService; + import java.util.concurrent.Executors; + + public class PutObjectFromStreamAsync { + private static final Logger logger = LoggerFactory.getLogger(PutObjectFromStreamAsync.class); + + public static void main(String[] args) { + String bucketName = "amzn-s3-demo-bucket-" + UUID.randomUUID(); // Change bucket name. + String key = UUID.randomUUID().toString(); + + AsyncExampleUtils.createBucket(bucketName); + try { + PutObjectFromStreamAsync example = new PutObjectFromStreamAsync(); + S3AsyncClient s3AsyncClientCrt = S3AsyncClient.crtCreate(); + PutObjectResponse putObjectResponse = example.putObjectFromStreamCrt(s3AsyncClientCrt, bucketName, key); + logger.info("Object {} etag: {}", key, putObjectResponse.eTag()); + logger.info("Object {} uploaded to bucket {}.", key, bucketName); + } catch (SdkException e) { + logger.error(e.getMessage(), e); + } finally { + AsyncExampleUtils.deleteObject(bucketName, key); + AsyncExampleUtils.deleteBucket(bucketName); + } + } @@ -38,2 +62 @@ Use the [AWS CRT-based S3 Client](https://docs.aws.amazon.com/sdk-for-java/lates - * @param s33CrtAsyncClient - To upload content from a stream of unknown size, use the AWS CRT-based S3 client. For more information, see - * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/crt-based-s3-client.html. + * @param s33CrtAsyncClient - To upload content from a stream of unknown size, use can the AWS CRT-based S3 client. @@ -44 +67,6 @@ Use the [AWS CRT-based S3 Client](https://docs.aws.amazon.com/sdk-for-java/lates - public PutObjectResponse putObjectFromStream(S3AsyncClient s33CrtAsyncClient, String bucketName, String key) { + public PutObjectResponse putObjectFromStreamCrt(S3AsyncClient s33CrtAsyncClient, String bucketName, String key) { + + // AsyncExampleUtils.randomString() returns a random string up to 100 characters. + String randomString = AsyncExampleUtils.randomString(); + logger.info("random string to upload: {}: length={}", randomString, randomString.length()); + InputStream inputStream = new ByteArrayInputStream(randomString.getBytes()); @@ -46,2 +74,4 @@ Use the [AWS CRT-based S3 Client](https://docs.aws.amazon.com/sdk-for-java/lates - BlockingInputStreamAsyncRequestBody body = - AsyncRequestBody.forBlockingInputStream(null); // 'null' indicates a stream will be provided later. + // Executor required to handle reading from the InputStream on a separate thread so the main upload is not blocked. + ExecutorService executor = Executors.newSingleThreadExecutor(); + // Specify `null` for the content length when you don't know the content length. + AsyncRequestBody body = AsyncRequestBody.fromInputStream(inputStream, null, executor); @@ -51,0 +82,57 @@ Use the [AWS CRT-based S3 Client](https://docs.aws.amazon.com/sdk-for-java/lates + PutObjectResponse response = responseFuture.join(); // Wait for the response. + logger.info("Object {} uploaded to bucket {}.", key, bucketName); + executor.shutdown(); + return response; + } + } + + + +Use the standard [ asynchronous S3 client with multipart upload enabled](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/s3-async-client-multipart.html#s3-async-client-mp-on). + + + import com.example.s3.util.AsyncExampleUtils; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import software.amazon.awssdk.core.async.AsyncRequestBody; + import software.amazon.awssdk.core.exception.SdkException; + import software.amazon.awssdk.services.s3.S3AsyncClient; + import software.amazon.awssdk.services.s3.model.PutObjectResponse; + + import java.io.ByteArrayInputStream; + import java.io.InputStream; + import java.util.UUID; + import java.util.concurrent.CompletableFuture; + import java.util.concurrent.ExecutorService; + import java.util.concurrent.Executors; + + public class PutObjectFromStreamAsyncMp { + private static final Logger logger = LoggerFactory.getLogger(PutObjectFromStreamAsyncMp.class); + + public static void main(String[] args) { + String bucketName = "amzn-s3-demo-bucket-" + UUID.randomUUID(); // Change bucket name. + String key = UUID.randomUUID().toString(); + + AsyncExampleUtils.createBucket(bucketName); + try { + PutObjectFromStreamAsyncMp example = new PutObjectFromStreamAsyncMp(); + S3AsyncClient s3AsyncClientMp = S3AsyncClient.builder().multipartEnabled(true).build(); + PutObjectResponse putObjectResponse = example.putObjectFromStreamMp(s3AsyncClientMp, bucketName, key); + logger.info("Object {} etag: {}", key, putObjectResponse.eTag()); + logger.info("Object {} uploaded to bucket {}.", key, bucketName); + } catch (SdkException e) { + logger.error(e.getMessage(), e); + } finally { + AsyncExampleUtils.deleteObject(bucketName, key); + AsyncExampleUtils.deleteBucket(bucketName); + } + } + + /** + * @param s3AsyncClientMp - To upload content from a stream of unknown size, use can the S3 asynchronous client with multipart enabled. + * @param bucketName - The name of the bucket. + * @param key - The name of the object. + * @return software.amazon.awssdk.services.s3.model.PutObjectResponse - Returns metadata pertaining to the put object operation. + */ + public PutObjectResponse putObjectFromStreamMp(S3AsyncClient s3AsyncClientMp, String bucketName, String key) { + @@ -54,0 +142 @@ Use the [AWS CRT-based S3 Client](https://docs.aws.amazon.com/sdk-for-java/lates + InputStream inputStream = new ByteArrayInputStream(randomString.getBytes()); @@ -56,2 +144,7 @@ Use the [AWS CRT-based S3 Client](https://docs.aws.amazon.com/sdk-for-java/lates - // Provide the stream of data to be uploaded. - body.writeInputStream(new ByteArrayInputStream(randomString.getBytes())); + // Executor required to handle reading from the InputStream on a separate thread so the main upload is not blocked. + ExecutorService executor = Executors.newSingleThreadExecutor(); + // Specify `null` for the content length when you don't know the content length. + AsyncRequestBody body = AsyncRequestBody.fromInputStream(inputStream, null, executor); + + CompletableFuture<PutObjectResponse> responseFuture = + s3AsyncClientMp.putObject(r -> r.bucket(bucketName).key(key), body); @@ -60,0 +154 @@ Use the [AWS CRT-based S3 Client](https://docs.aws.amazon.com/sdk-for-java/lates + executor.shutdown(); @@ -74 +167,0 @@ Use the [Amazon S3 Transfer Manager](https://docs.aws.amazon.com/sdk-for-java/la - import software.amazon.awssdk.core.async.BlockingInputStreamAsyncRequestBody; @@ -80,0 +174 @@ Use the [Amazon S3 Transfer Manager](https://docs.aws.amazon.com/sdk-for-java/la + import java.io.InputStream; @@ -81,0 +176,23 @@ Use the [Amazon S3 Transfer Manager](https://docs.aws.amazon.com/sdk-for-java/la + import java.util.concurrent.ExecutorService; + import java.util.concurrent.Executors; + + public class UploadStream { + private static final Logger logger = LoggerFactory.getLogger(UploadStream.class); + + public static void main(String[] args) { + String bucketName = "amzn-s3-demo-bucket" + UUID.randomUUID(); + String key = UUID.randomUUID().toString(); + + AsyncExampleUtils.createBucket(bucketName); + try { + UploadStream example = new UploadStream(); + CompletedUpload completedUpload = example.uploadStream(S3TransferManager.create(), bucketName, key); + logger.info("Object {} etag: {}", key, completedUpload.response().eTag()); + logger.info("Object {} uploaded to bucket {}.", key, bucketName); + } catch (SdkException e) { + logger.error(e.getMessage(), e); + } finally { + AsyncExampleUtils.deleteObject(bucketName, key); + AsyncExampleUtils.deleteBucket(bucketName); + } + } @@ -84,2 +201 @@ Use the [Amazon S3 Transfer Manager](https://docs.aws.amazon.com/sdk-for-java/la - * @param transferManager - To upload content from a stream of unknown size, use the S3TransferManager based on the AWS CRT-based S3 client. - * For more information, see https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/transfer-manager.html. + * @param transferManager - To upload content from a stream of unknown size, you can use the S3TransferManager based on the AWS CRT-based S3 client. @@ -92,2 +208,9 @@ Use the [Amazon S3 Transfer Manager](https://docs.aws.amazon.com/sdk-for-java/la - BlockingInputStreamAsyncRequestBody body = - AsyncRequestBody.forBlockingInputStream(null); // 'null' indicates a stream will be provided later. + // AsyncExampleUtils.randomString() returns a random string up to 100 characters. + String randomString = AsyncExampleUtils.randomString(); + logger.info("random string to upload: {}: length={}", randomString, randomString.length()); + InputStream inputStream = new ByteArrayInputStream(randomString.getBytes()); + + // Executor required to handle reading from the InputStream on a separate thread so the main upload is not blocked. + ExecutorService executor = Executors.newSingleThreadExecutor(); + // Specify `null` for the content length when you don't know the content length. + AsyncRequestBody body = AsyncRequestBody.fromInputStream(inputStream, null, executor); @@ -100,8 +223,3 @@ Use the [Amazon S3 Transfer Manager](https://docs.aws.amazon.com/sdk-for-java/la - // AsyncExampleUtils.randomString() returns a random string up to 100 characters. - String randomString = AsyncExampleUtils.randomString(); - logger.info("random string to upload: {}: length={}", randomString, randomString.length()); - - // Provide the stream of data to be uploaded. - body.writeInputStream(new ByteArrayInputStream(randomString.getBytes())); - - return upload.completionFuture().join(); + CompletedUpload completedUpload = upload.completionFuture().join(); + executor.shutdown(); + return completedUpload;