Rails: allow download of files stored on S3 without showing the actual S3 URL to user Rails: allow download of files stored on S3 without showing the actual S3 URL to user ruby-on-rails ruby-on-rails

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

This issue is also somewhat related.


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