Rails: allow download of files stored on S3 without showing the actual S3 URL to user
You can create your s3 objects as private and generate temporary public urls for them with url_for method (aws-s3 gem). This way you don't stream files through your app servers, which is more scalable. It also allows putting session based authorization (e.g. devise in your app), tracking of download events, etc.
In order to do this, change direct links to s3 hosted files into links to controller/action which creates temporary url and redirects to it. Like this:
class HostedFilesController < ApplicationController def show s3_name = params[:id] # sanitize name here, restrict access to only some paths, etc AWS::S3::Base.establish_connection!( ... ) url = AWS::S3::S3Object.url_for(s3_name, YOUR_BUCKET, :expires_in => 2.minutes) redirect_to url endend
Hiding of amazon domain in download urls is usually done with DNS aliasing. You need to create CNAME record aliasing your subdomain, e.g. downloads.mydomain
, to s3.amazonaws.com
. Then you can specify :server
option in AWS::S3::Base.establish_connection!(:server => "downloads.mydomain", ...)
and S3 gem will use it for generating links.
Yes, this is possible - just fetch the remote file with Rails and either store it temporarily on your server or send it directly from the buffer. The problem with this is of course the fact that you need to fetch the file first before you can serve it to the user. See this thread for a discussion, their solution is something like this:
#environment.rbrequire 'open-uri'#controllerdef index data = open(params[:file]) send_data data, :filename => params[:name], ...end
First you need create a CNAME in your domain, like explain here.
Second you need create a bucket with the same name that you put in CNAME.
And to finish you need add this configurations in your config/initializers/carrierwave.rb:
CarrierWave.configure do |config| ... config.asset_host = 'http://bucket_name.your_domain.com' config.fog_directory = 'bucket_name.your_domain.com' ...end