Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Fog with Ruby to generate a Pre-signed URL to PUT a file in Amazon S3

I am using the Fog gem to generate presigned urls. I can do this successfully to get read access to the file. Here's what I do:

    fog_s3 = Fog::Storage.new({
          :provider                 => 'AWS',
          :aws_access_key_id        => key,
          :aws_secret_access_key    => secret
    })
    object_path = 'foo.wav' 
    expiry = Date.new(2014,2,1).to_time.to_i
    url = fog_s3.directories.new(:key => bucket).files.new(:key => object_path).url(expiry,path_style: true)

But this doesn't work when I try to upload the file. Is there a way to specify the http verb so it would be a PUT and not a GET?

EDIT I see a method: put_object_url which might help. I don't know how access it.

Thanks

EDIT based upon your suggestion:

It helped - it got me a PUT - not GET. However, I'm still having issues. I added content type:

    headers = { "Content-Type" => "audio/wav" }
    options = { path_style: true }
    object_path = 'foo.wav' 
    expiry = Date.new(2014,2,1).to_time.to_i  
    url = fog_s3.put_object_url(bucket,object_path, expiry, headers, options)

but the url does not contain Content-Type in it. When done from Javascript in HTML I get the Content-Type in the url and that seems to work. Is this an issue with Fog? or is my header incorrect?

like image 434
Joe R Avatar asked Jan 30 '14 15:01

Joe R


1 Answers

I think put_object_url is indeed what you want. If you follow the url method back to where it is defined, you can see it uses a similar method underlying it called get_object_url here (https://github.com/fog/fog/blob/dc7c5e285a1a252031d3d1570cbf2289f7137ed0/lib/fog/aws/models/storage/files.rb#L83). You should be able to do something similar and can do so by calling this method from the fog_s3 object you already created above. It should end up just looking like this:

headers = {}
options = { path_style: true }
url = fog_s3.put_object_url(bucket, object_path, expires, headers, options)

Note that unlike get_object_url there is an extra headers option snuck in there (which you can use to do stuff like set Content-Type I believe).

Hope that sorts it for you, but just let me know if you have further questions. Thanks!

Addendum

Hmm, seems there may be a bug related to this after all (I'm wondering now how much this portion of the code has been exercised). I think you should be able to work around it though (but I'm not certain). I suspect you can just duplicate the value in the options as a query param also. Could you try something like this?

headers = query = { 'Content-Type' => 'audio/wav' }
options = { path_style: true, query: query }
url = fog_s3.put_object_url(bucket, object_path, expires, headers, options)

Hopefully that fills in the blanks for you (and if so we can think some more about fixing that behavior within fog if it makes sense to do so). Thanks!

like image 65
geemus Avatar answered Nov 15 '22 06:11

geemus