Carrierwave & Amazon S3 file downloading/uploading
Asked Answered
R

1

11

I have a rails 3 app with an UploadsUploader and a Resource model on which this is mounted. I recently switched to using s3 storage and this has broken my ability to download files using the send_to method. I can enable downloading using the redirect_to method which is just forwarding the user to an authenticated s3 url. I need to authenticate file downloads and I want the url to be http://mydomainname.com/the_file_path or http://mydomainname.com/controller_action_name/id_of_resource so I am assuming I need to use send_to, but is there a way of doing that using the redirect_to method? My current code follows. Resources_controller.rb

def download
  resource = Resource.find(params[:id])
    if resource.shared_items.find_by_shared_with_id(current_user) or resource.user_id == current_user.id
        filename = resource.upload_identifier
        send_file "#{Rails.root}/my_bucket_name_here/uploads/#{filename}"
    else
        flash[:notice] = "You don't have permission to access this file."
        redirect_to resources_path
    end
end

carrierwave.rb initializer:

CarrierWave.configure do |config|
  config.fog_credentials = {
    :provider               => 'AWS',       # required
    :aws_access_key_id      => 'xxxx',       # copied off the aws site
    :aws_secret_access_key  => 'xxxx',       # 
  }

  config.fog_directory  = 'my_bucket_name_here'                     # required
  config.fog_host       = 'https://localhost:3000'            # optional, defaults to nil
  config.fog_public     = false                                   # optional, defaults to true
  config.fog_attributes = {'Cache-Control'=>'max-age=315576000'}  # optional, defaults to {}
end

upload_uploader.rb

class UploadUploader < CarrierWave::Uploader::Base
  storage :fog

  def store_dir
    "uploads"
  end
end

All of this throws the error:

Cannot read file /home/tom/Documents/ruby/rails/circlshare/My_bucket_name_here/uploads/Picture0024.jpg

I have tried reading up about carrierwave, fog, send_to and all of that but everything I have tried hasn't been fruitful as yet. Uploading is working fine and I can see the files in s3 bucket. Using re_direct would be great as the file wouldn't pass through my server. Any help appreciated. Thanks.

Rialto answered 4/9, 2011 at 9:51 Comment(0)
M
6

Looks like you want to upload to S3, but have not-public URLs. Instead of downloading the file from S3 and using send_file, you can redirect the user to the S3 authenticated URL. This URL will expire and only be valid for a little while (for the user to download).

Check out this thread: http://groups.google.com/group/carrierwave/browse_thread/thread/2f727c77864ac923

Since you're already setting fog_public to false, do you get an authenticated (i.e. signed) url when calling resource.upload_url

Manganate answered 4/9, 2011 at 16:38 Comment(2)
I do get an authenticated url and the redirect_to method works. Presumably I'll have to tell my users to 'Right-click to save' or their browser might open images in the browser revealing the amazon url - which, while not being a problem technically, would just look a bit amateur. Or is there a way I could obscure the URL from the user? Thanks for the help.Rialto
@Rialto -- this is precisely what 37signals does with their basecamp file uploads. I wouldn't bother with right-click-to-save, but that's up to you.Manganate

© 2022 - 2024 — McMap. All rights reserved.