3

I'm attempting to access files on my S3 server via my rails app. Currently the app is able to create a presigned_url through the aws-sdk v2 gem and then redirect to display the file (I've mostly been using images as the file). This all works very well but rather than simply displaying the file in the browser, I would REALLY like to trigger an automatic download of that file.

As it stands with the redirect, my code is as follows:

def get
    asset = current_user.assets.find_by_id(params[:id])

    if asset
        s3 = Aws::S3::Resource.new
        bucketlink = s3.bucket(ENV['S3_BUCKET_NAME']).object(asset.uploaded_file.path).presigned_url(:get, expires_in: 3600)
        redirect_to bucketlink
    else
        flash[:error]="Don't be cheeky!  Mind your own assets"
        redirect_to assets_path
    end
end

Can anyone give me a clue as to how I can trigger a download of this file? Many thanks in advance.

John Rotenstein
  • 241,921
  • 22
  • 380
  • 470
neanderslob
  • 2,633
  • 6
  • 40
  • 82

1 Answers1

10

I know nothing about ruby, so this is something of a guess.. but the based on my expertise working directly with the REST API and a quick search of the SDK docs for a specific string I had in mind, I think you are looking for something like this:

bucketlink = s3.bucket(ENV['S3_BUCKET_NAME']).object(asset.uploaded_file.path).presigned_url(:get, expires_in: 3600, response_content_disposition: 'attachment; filename=myfile.jpg')

When &response-content-disposition=value appears in the query string of an authenticated GET request, S3 returns that value as the Content-Disposition: header in the response. "attachment" means "download, don't display" and the filename is the filename the browser will typically use, or offer as the default if a "save as" prompt is shown... so the filename the user downloads can be different than the filename as stored in S3. 'attachment;<space>filename=<target-filename>' is a single string, which you'll want to build to contain something sensible, rather than "myfile.jpg" of course.

Michael - sqlbot
  • 169,571
  • 25
  • 353
  • 427
  • 1
    Wow, I am impressed. Thanks a lot. – neanderslob Oct 09 '15 at 05:31
  • For the next guy who comes along, I didn't ultimately need the file name so I ended up using the following: `bucketlink = s3.bucket(ENV['S3_BUCKET_NAME']).object(asset.uploaded_file.path).presigned_url(:get, expires_in: 3600, response_content_disposition: 'attachment')` – neanderslob Oct 09 '15 at 06:19
  • @neanderslob I'm trying to do this exact thing but am running into an infinite loop problem [outlined here](http://stackoverflow.com/questions/42687386/rails-download-of-aws-s3-file-using-presigned-post-fatal-exception). Did you run into this? How do you call your get method? – CChandler81 Mar 09 '17 at 08:26