0

I set up my Rails app to upload files directly to AWS S3 using this tutorial and it works great. Now I'm working on the direct download piece using the same approach in this SO post. When I try and trigger the download it hangs and then finally returns the following error:

fatal at /user/doc_uploads/download exception reentered

The puts in the code below show what appears to be an infinite loop on the server. I simply don't know enough about how this code is supposed to work to figure this out. Please help!

doc_uploads_controller.rb

def get
    @doc_download = @user.doc_uploads.find_by_id(params[:id])
    if @doc_download
      key = @doc_download.file_url.split('amazonaws.com/')[1]
      puts key
      puts S3_BUCKET_NAME
      bucketlink = S3_BUCKET_NAME.object(key).presigned_url(‌​:get, expires_in: 3600)
      puts bucketlink
      redirect_to bucketlink
    else
      flash[:error]="Something went wrong."
      redirect_to user_dashboard_path
    end
  end

aws.rb:

Aws.config.update({
  region: 'us-east-1',
  credentials: Aws::Credentials.new(ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY']),
})

S3_BUCKET_NAME = Aws::S3::Resource.new.bucket(ENV['S3_BUCKET_NAME'])

routes.rb:

get 'user/doc_uploads/download', to: 'doc_uploads#get'

view:

<% @doc_uploads.each do |doc_upload| %>
...
      <%= link_to user_doc_uploads_download_path(id: doc_upload.id), target: '_blank' do %>
        <p class="glyphicon glyphicon-download-alt"></p>
      <% end %>
...
<% end %>

Thanks in advance!

Community
  • 1
  • 1
CChandler81
  • 347
  • 3
  • 14
  • What output you are getting with `s3.bucket(ENV['S3_BUCKET_NAME']).object(parsed_url).presigned_url(‌​:get, expires_in: 3600)` – Dipak Gupta Mar 09 '17 at 05:37
  • @dipak-g If I add a puts for that to the code it doesn't output anything to the server. Is there another way to check? – CChandler81 Mar 09 '17 at 05:59
  • Edited the code to correct setting the key and with a more straightforward way to set bucketlink, however still get the infinite loop and fatal exception. – CChandler81 Mar 09 '17 at 07:25

2 Answers2

0

If you are able to get url properly in your code, So you can also able to read image from that url.

Try this:

def get
  @doc_download = @user.doc_uploads.find_by_id(params[:id])
  if @doc_download
    data = open(@doc_download.file_url) 
    send_data data.read, filename: 'filename', stream: 'true', buffer_size: '4096'
  else
    flash[:error]="Something went wrong."
    redirect_to user_dashboard_path
  end
end
Dipak Gupta
  • 7,321
  • 1
  • 20
  • 32
  • With this method wouldn't the S3 file have to have permissions set such that the whole world can view it? I only want the logged in user to be able to view the doc and have the S3 permissions set so that only the authenticated user can get. I would also like to avoid downloading the file to my server. – CChandler81 Mar 09 '17 at 07:32
  • As per my understanding this url not accessible outside of your application, because key and other credential are picking from your initialize file. try copy url and paste in browser it won't open. Logged in user check you can implement in code. First check my code is working or not. – Dipak Gupta Mar 09 '17 at 07:46
  • Your code as written results in a `No such file or directory @ rb_sysopen` error. The file_url that gets saved to the database on upload is '//[bucket name].s3.amazonaws.com/[key]'. If I modify your code to use the full link from the S3 Management Console I get a 403 Forbidden error, which is what I would expect in that case. – CChandler81 Mar 09 '17 at 08:00
0

Found a recent post here and got their solution working, as:

presigner = Aws::S3::Presigner.new
url = presigner.presigned_url(:get_object, bucket: ENV['S3_BUCKET_NAME'], key: key, expires_in: 3600, response_content_disposition: "attachment").to_s
redirect_to url
Community
  • 1
  • 1
CChandler81
  • 347
  • 3
  • 14