Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Carrierwave uploading with s3 and fog

been trying to search the reason for this error for a long time and can't seem to find any...

So I have a rails app, and I utilize carrierwave for pictures uploading. I also want to utilize Amazon S3 for file upload storage in my app.

Initially as I am developing the app I allowed file uploads to be on the on :file, i.e.

image_uploader.rb

# Choose what kind of storage to use for this uploader:
  storage :file
# storage :fog

Now upon finishing up development and placing it live (I use heroku), I decided to change the carrierwave storage to S3 to test it locally.

image_uploader.rb

# Choose what kind of storage to use for this uploader:
# storage :file
storage :fog

However, now when I try to upload a picture (be it for user avatar, etc) I get this error:

Excon::Errors::Forbidden in UsersController#update
Expected(200) <=> Actual(403 Forbidden)
request => {:connect_timeout=>60, :headers=>{"Content-Length"=>74577, "x-amz-   acl"=>"private", "Content-Type"=>"image/png", "Date"=>"Sun, 26 Feb 2012 10:00:43 +0000",  "Authorization"=>"AWS AKIAJOCDPFOU7UTT4HOQ:8ZnOy7X71nQAM87yraSI24Y5bSw=", "Host"=>"s3.amazonaws.com:443"}, :instrumentor_name=>"excon", :mock=>false, :read_timeout=>60, :retry_limit=>4, :ssl_verify_peer=>true, :write_timeout=>60, :host=>"s3.amazonaws.com", :path=>"/uploads//uploads%2Fuser%2Favatar%2F1%2Fjeffportraitmedium.png", :port=>"443", :query=>nil, :scheme=>"https", :body=>"\x89PNG\r\n\x1A\n\x00\x00\x00\rIHDR\x00\x00\x00\xC2\x00\x00\x00\xC3\b\x06\x00\x00\x00\xD0\xBD\xCE\x94\x00\x00\nCiCCPICC Profile\x00\x00x\x01\x9D\x96wTSY\x13\xC0\xEF{/\xBD\xD0\x12B\x91\x12z\rMJ\x00\x91\x12z\x91^E%$\
...
# The code you see above to the far right repeats itself a LOT
...
1@\x85\xB5\t\xFC_y~\xA6=:\xB2\xD0^\xBB~i\xBB\x82\x8F\x9B\xAF\xE7\x04m\xB2i\xFF\x17O\x94S\xF7l\x87\xA8&\x00\x00\x00\x00IEND\xAEB`\x82", :expects=>200, :idempotent=>true, :method=>"PUT"}
response => #<Excon::Response:0x007fc88ca9f3d8 @body="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>8EFA56C0DDDC8878</RequestId><HostId>1OxWXppSSUq1MFjQwvnFptuCM3gKOuKdlQQyVSEgvzzv4Aj+r2hSFM2UUw2NYyrR</HostId></Error>", @headers={"x-amz-request-id"=>"8EFA56C0DDDC8878", "x-amz-id-2"=>"1OxWXppSSUq1MFjQwvnFptuCM3gKOuKdlQQyVSEgvzzv4Aj+r2hSFM2UUw2NYyrR", "Content-Type"=>"application/xml", "Transfer-Encoding"=>"chunked", "Date"=>"Sun, 26 Feb 2012 10:00:47 GMT", "Connection"=>"close", "Server"=>"AmazonS3"}, @status=403>

And then it says this as well for my application trace:

app/controllers/users_controller.rb:39:in `update'

And my REQUEST parameters:

{"utf8"=>"✓",
"_method"=>"put",
"authenticity_token"=>"DvADD1vYpCLcghq+EIOwVSjsfmAWCHhtA3VI5VGD/q8=",
"user"=>{"avatar"=>#<ActionDispatch::Http::UploadedFile:0x007fc88cde76f8     
@original_filename="JeffPortraitMedium.png",
@content_type="image/png",
@headers="Content-Disposition: form-data; name=\"user[avatar]\";   
filename=\"JeffPortraitMedium.png\"\r\nContent-Type: image/png\r\n",
@tempfile=#<File:/var/folders/vg/98nv58ss4v7gcbf8px_8dyqc0000gq/T/RackMultipart20120226- 19096-1ppu2sr>>,
"remote_avatar_url"=>"",
"name"=>"Jeff Lam ",
"email"=>"[email protected]",
"user_bio"=>"Tester Hello",
"shop"=>"1"},
"commit"=>"Update Changes",
"id"=>"1"}

Here's my users_controller.rb partial code:

def update
    @user = User.find(params[:id])
    if @user.update_attributes(params[:user]) 
        redirect_back_or root_path
        flash[:success] = "Your have updated your settings successfully."
    else
        flash.now[:error] = "Sorry! We are unable to update your settings. Please check your fields and try again."
        render 'edit'
    end
end

My image_uploader.rb code

# encoding: utf-8
class ImageUploader < CarrierWave::Uploader::Base

  # Include RMagick or MiniMagick support:
  # include CarrierWave::RMagick
  include CarrierWave::MiniMagick

  # Choose what kind of storage to use for this uploader:
  # storage :file
  storage :fog

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  # Provide a default URL as a default if there hasn't been a file uploaded:
  # def default_url
  #   "/images/fallback/" + [version_name, "default.png"].compact.join('_')
  # end

  # Process files as they are uploaded:
  # process :scale => [200, 300]
  #
  # def scale(width, height)
  #   # do something
  # end

  # Create different versions of your uploaded files:
  version :thumb do
    process resize_to_fill: [360, 250]
  end

  version :cover_photo_thumb do
    process resize_to_fill: [1170, 400]
  end

  version :event do
    process resize_to_fill: [550, 382]
  end

  version :product do
    process resize_to_fit: [226, 316]
  end

  # Add a white list of extensions which are allowed to be uploaded.
  # For images you might use something like this:
  def extension_white_list
    %w(jpg jpeg gif png)
  end

  # Override the filename of the uploaded files:
  # Avoid using model.id or version_name here, see uploader/store.rb for details.
  # def filename
  #   "something.jpg" if original_filename
  # end 

  # fix for Heroku, unfortunately, it disables caching, 
  # see: https://github.com/jnicklas/carrierwave/wiki/How-to%3A-Make-Carrierwave-work-on-Heroku
  def cache_dir
    "#{Rails.root}/tmp/uploads"
  end

end

Finally, my fog.rb file in the config/initializers

CarrierWave.configure do |config|
  config.fog_credentials = {
    :provider               => 'AWS',       # required
    :aws_access_key_id      => 'ACCESS_KEY',       # required
    :aws_secret_access_key  => 'SECRET_ACCESS_KEY/ZN5SkOUtOEHd61/Cglq9',       # required
    :region                 => 'Singapore'  # optional, defaults to 'us-east-1' 
  }
  config.fog_directory  = 'ruuva/'                     # required
  config.fog_public     = false                          # optional, defaults to true
end

I'm actually quite confused on some of the things in my fog.rb. Firstly, should I change my region to Singapore if I created a bucket called "ruuva", with region "Singapore" on my amazon s3 account?

Thank you to anyone that can help in advance!

like image 980
Jeff Lam Tian Hung Avatar asked Feb 26 '12 10:02

Jeff Lam Tian Hung


2 Answers

First make sure you use the right credentials by not setting custom region and custom directory (create a fake bucket for free in the default region)

Then I think you are not using the right name for the region. Try setting your region like this:

:region  => 'ap-southeast-1'
like image 72
rpechayr Avatar answered Sep 17 '22 18:09

rpechayr


We were facing the same problem and fixed that changing the user's permission associated to your access key, changing it to "Power User". Check if you need your user to be power user before put it into productions.

like image 40
David Lojudice Sb. Avatar answered Sep 21 '22 18:09

David Lojudice Sb.