Using send_file to download a file from Amazon S3?
Keep Things Simple For The User
I think the best way to handle this is using an expiring S3 url. The other methods have the following issues:
- The file downloads to the server first and then to the user.
- Using
send_data
doesn't produce the expected "browser download". - Ties up the Ruby process.
- Requires an additional
download
controller action.
My implementation looks like this:
In your attachment.rb
def download_url
S3 = AWS::S3.new.buckets[ 'bucket_name' ] # This can be done elsewhere as well,
# e.g config/environments/development.rb
url_options = {
expires_in: 60.minutes,
use_ssl: true,
response_content_disposition: "attachment; filename=\"#{attachment_file_name}\""
}
S3.objects[ self.path ].url_for( :read, url_options ).to_s
end
In your views
<%= link_to 'Download Avicii by Avicii', attachment.download_url %>
That's it.
If you still wanted to keep your download
action for some reason then just use this:
In your attachments_controller.rb
def download
redirect_to @attachment.download_url
end
Thanks to guilleva for his guidance.
In order to send a file from your web server,
you need to download it from S3 (see @nzajt's answer) or
you can
redirect_to @attachment.file.expiring_url(10)
You can also use send_data
.
I like this option because you have better control. You are not sending users to s3, which might be confusing to some users.
I would just add a download method to the AttachmentsController
def download
data = open("https://s3.amazonaws.com/PATTH TO YOUR FILE")
send_data data.read, filename: "NAME YOU WANT.pdf", type: "application/pdf", disposition: 'inline', stream: 'true', buffer_size: '4096'
end
and add the route
get "attachments/download"