Abhishek Jain
Abhishek Jain

Reputation: 23

AWS Java SDK 2.0 S3 presigned URL public object access

Creating presigned url for file upload in itself is working fine. But uploading the file through the generated URL by default makes it private and hence cannot be accessed through it's URL

I have to manually go to the console and make the file public to be accessible from it's URL

Here is my code

String bucketName = "<bucket-name>";
String keyName = "<file-name>";

S3Presigner presigner = S3Presigner.builder().region(Region.AP_SOUTH_1).build();

PutObjectRequest objectRequest = PutObjectRequest.builder()
        .bucket(bucketName)
        .key(keyName)
        .build();

PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder()
        .signatureDuration(Duration.ofMinutes(3))
        .putObjectRequest(objectRequest)
        .build();

PresignedPutObjectRequest presignedRequest = presigner.presignPutObject(presignRequest);

System.out.println("Pre-signed 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());   

presigner.close();

In NodeJs we specify that we want the file to be publicly accessible so I found it's java sdk equivalent like this

PutObjectRequest objectRequest = PutObjectRequest.builder()
        .bucket(bucketName)
        .key(keyName)
        .acl(ObjectCannedACL.PUBLIC_READ)
        .build();

But when uploading through the URL thus generated, I'm getting a singature mismatch error

The request signature we calculated does not match the signature you provided. Check your key and signing method

What am I doing wrong? Is it not the correct way to make the file publicly accessible? If not, how should I do it?

Upvotes: 0

Views: 2439

Answers (2)

user8787628
user8787628

Reputation:

This should do the trick:

new PutObjectRequest("xxx", "xxx, fis, metadata).withCannedAcl(CannedAccessControlList.PublicRead));

Upvotes: 0

Abhishek Jain
Abhishek Jain

Reputation: 23

I posted the same question on AWS's github for java-sdk and found the solution.

Adding .acl(ObjectCannedACL.PUBLIC_READ) in PutObjectRequest.builder() will add x-amz-acl in the header as opposed to the query where it is needed

Here's how to add it in the query

AwsRequestOverrideConfiguration override = AwsRequestOverrideConfiguration.builder()
        .putRawQueryParameter("x-amz-acl", "private")
        .build();

PutObjectRequest putObjectRequest = PutObjectRequest.builder()
        .bucket(bucketName)
        .key(keyName)
        .overrideConfiguration(override)
        .build();

The solution works perfectly. Thought it might help someone else as well

For more info, see github

Upvotes: 2

Related Questions