amazon-archives/aws-sdk-core-ruby

S3 presigned_urls don't work when filenames contain spaces

Closed this issue · 2 comments

I've uploaded a private file to an S3 bucket with the filename Image Logo.png, which S3 corrects to Image+Logo.png. Through the online S3 interface I can navigate to the interface and view the file; the URL looks something like this: https://s3.amazonaws.com/bucket/path/to/file/Image+Logo.png?signing=stuff

However, when I try to use this gem's Aws::S3::Object.presigned_url method, the path's incorrectly encoding that space as a %2B, which means I get an access denied error.

I noticed that Presigner is using Seahorse::Util.uri_escape, which includes .gsub('+', '%20'), but note that %20 is different from %2B. I did some other sporadic digging but didn't turn up anything else that might be related.

Let me know if I can provide more information.

When you uploaded the file to Amazon S3, the key is actually stored as "Image Logo.png", not "Image+Logo.png". The plus sign you are seeing in the URL is not actually part of the key, it is simply the URL encoded value for the space character. Another alternative way to encode the space character is %20 (which is what the SDK uses).

To correctly generate a pre-signed URL for your object, you should be doing the following:

s3 = Aws::S3::Resource.new
puts s3.bucket('name').object('Image Logo.png').presigned_url(:get)
#=> "https://..."

What is happening is you are given the plus sign as part of the object key, which is then being encoded to a literal plus sign character, not space, which is %2B.

Ah, thanks for the insight. It works now!