Working with Amazon S3 Presigned URLs - AWS SDK for Java
AWS services or capabilities described in AWS documentation might vary by Region. To see the differences applicable to the China Regions, see Getting Started with AWS services in China.

At Amazon Web Services (AWS), we’re focused on finding ways to improve our products and provide a better customer experience. To do that, we need your feedback. Please take 5 minutes of your time to share insights regarding your experience with Java Spring and your need for Spring integration with AWS.

Click here to take a quick survey

This survey is hosted by an external company (Qualtrics), so the link above does not lead to our website. Please note that AWS will own the data gathered via this survey, and will not share the information/results collected with survey respondents. AWS handles your information as described in the AWS Privacy Notice.

Working with Amazon S3 Presigned URLs

You can use a S3Presigner object to sign an Amazon S3SdkRequest so that it’s executed without requiring authentication on the part of the caller. For example, assume Alice has access to an S3 object, and she wants to temporarily share access to that object with Bob. Alice can generate a pre-signed GetObjectRequest object to secure share with Bob so that he can download the object without requiring access to Alice’s credentials.

Generate a Presigned URL and Upload an Object

Build a S3Presigner object that represents the client object. Next create a PresignedPutObjectRequest object that can be executed at a later time without requiring additional signing or authentication. When you create this object, you can specify the bucket name and the key name. In addition, you can also specify the time in minutes that the bucket can be accessed without using credentials by invoking the signatureDuration method (as shown in the following code example).

You can use the PresignedPutObjectRequest object to obtain the URL by invoking its url method.

Imports

import java.io.IOException; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.time.Duration; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.S3Exception; import software.amazon.awssdk.services.s3.presigner.model.PresignedPutObjectRequest; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest;

Code

The following Java code example uploads content to a presigned S3 bucket.

public static void signBucket(S3Presigner presigner, String bucketName, String keyName) { try { PutObjectRequest objectRequest = PutObjectRequest.builder() .bucket(bucketName) .key(keyName) .contentType("text/plain") .build(); PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder() .signatureDuration(Duration.ofMinutes(10)) .putObjectRequest(objectRequest) .build(); PresignedPutObjectRequest presignedRequest = presigner.presignPutObject(presignRequest); System.out.println("Presigned URL to upload a file to: " + presignedRequest.url()); System.out.println("Which HTTP method needs to be used when uploading a file: " + presignedRequest.httpRequest().method()); // Upload content to the Amazon S3 bucket by using this URL URL url = presignedRequest.url(); // Create the connection and use it to upload the new object by using the presigned URL HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setRequestProperty("Content-Type","text/plain"); connection.setRequestMethod("PUT"); OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream()); out.write("This text was uploaded as an object by using a presigned URL."); out.close(); connection.getResponseCode(); System.out.println("HTTP response code is " + connection.getResponseCode()); } catch (S3Exception e) { e.getStackTrace(); } catch (IOException e) { e.getStackTrace(); }

See the complete example on GitHub.

Get a Presigned Object

Build a S3Presigner object that represents the client object. Next, create a GetObjectRequest object and specify the bucket name and key name. In addition, create a GetObjectPresignRequest object that can be executed at a later time without requiring additional signing or authentication. When you create this object, you can specify the time in minutes that the bucket can be accessed without using credentials by invoking the signatureDuration method (as shown in the following code example).

Invoke the presignGetObject method that belongs to the S3Presigner object to create a PresignedPutObjectRequest object. You can invoke this object’s url method to obtain the URL to use. Once you have the URL, you can use standard HTTP Java logic to read the contents of the bucket, as shown in the following Java code example.

Imports

import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.time.Duration; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.S3Exception; import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest; import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.utils.IoUtils;

Code

The following Java code example reads content from a presigned S3 bucket.

public static void getPresignedUrl(S3Presigner presigner, String bucketName, String keyName ) { try { GetObjectRequest getObjectRequest = GetObjectRequest.builder() .bucket(bucketName) .key(keyName) .build(); GetObjectPresignRequest getObjectPresignRequest = GetObjectPresignRequest.builder() .signatureDuration(Duration.ofMinutes(10)) .getObjectRequest(getObjectRequest) .build(); // Generate the presigned request PresignedGetObjectRequest presignedGetObjectRequest = presigner.presignGetObject(getObjectPresignRequest); // Log the presigned URL System.out.println("Presigned URL: " + presignedGetObjectRequest.url()); HttpURLConnection connection = (HttpURLConnection) presignedGetObjectRequest.url().openConnection(); presignedGetObjectRequest.httpRequest().headers().forEach((header, values) -> { values.forEach(value -> { connection.addRequestProperty(header, value); }); }); // Send any request payload that the service needs (not needed when isBrowserExecutable is true) if (presignedGetObjectRequest.signedPayload().isPresent()) { connection.setDoOutput(true); try (InputStream signedPayload = presignedGetObjectRequest.signedPayload().get().asInputStream(); OutputStream httpOutputStream = connection.getOutputStream()) { IoUtils.copy(signedPayload, httpOutputStream); } } // Download the result of executing the request try (InputStream content = connection.getInputStream()) { System.out.println("Service returned response: "); IoUtils.copy(content, System.out); } } catch (S3Exception e) { e.getStackTrace(); } catch (IOException e) { e.getStackTrace(); }

See the complete example on GitHub.