I am using the Java Amazon SDK to work with S3 for storing uploaded files. I would like to retain the original filename, and I am putting it at the end of the key, but I am also using virtual directory structure - something like <dirname>/<uuid>/<originalFilename>
.
The problem is that when I want to generate a presigned URL for downloading using the api like:
URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
return url.toExternalForm();
The sdk url escapes the entire key, including the slashes. While it still works, it means that the name of the file downloaded includes the entire key instead of just the original filename bit at the end. I know that it should be possible to do this without escaping the slashes, but I'm trying to avoid rewriting a lot of the code already in the SDK. Is there a common solution to this? I know I've used web apps that follow the same pattern and do not have the slash escape problem.
A presigned URL gives you access to the object identified in the URL, provided that the creator of the presigned URL has permissions to access that object.
Generating pre-signed URL using : var params = { Bucket: bucket, Expires: Settings. UrlGetTimeout, Key: record }; S3. getSignedUrl('getObject', params);
The presigned URLs are valid only for the specified duration. If you created a presigned URL using a temporary token, then the URL expires when the token expires, even if the URL was created with a later expiration time. Anyone who receives the presigned URL can then access the object.
The object key (or key name) uniquely identifies the object in an Amazon S3 bucket. Object metadata is a set of name-value pairs. For more information about object metadata, see Working with object metadata. When you create an object, you specify the key name, which uniquely identifies the object in the bucket.
This is a bug in the current Java SDK:
If you look at https://github.com/aws/aws-sdk-java/blob/master/src/main/java/com/amazonaws/services/s3/AmazonS3Client.java#L2820
The method presignRequest which is called internally has the following code:
String resourcePath = "/" +
((bucketName != null) ? bucketName + "/" : "") +
((key != null) ? ServiceUtils.urlEncode(key) : "") +
((subResource != null) ? "?" + subResource : "");
The key is URL encoded here before signing which I think is the error.
You might be able to inherit from the AmazonS3Client
and override the funcion to fix this.
In some places it is suggested to use url.getQuery()
and prefix this with your original awsURL (https://forums.aws.amazon.com/thread.jspa?messageID=356271). However as you said yourself this will produce an error, because the resource key will not match the signature.
The following problem might also be related, I did not check out the proposed workarround:
How to generate pre-signed Amazon S3 url for a vanity domain, using amazon sdk?
Amazon recognized and fixed a similar bug before: https://forums.aws.amazon.com/thread.jspa?messageID=418537
So I hope it will be fixed in the next version.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With