Rails download S3 file - ruby-on-rails

I'm uploading files to S3 with paperclip, and now I would like to download them from the same app. So I'm doing what lots of pages says, but if I use 'aws-sdk' it says that AWS::S3::S3Object method 'find' doesn't exist, and If I use 'aws-s3' gem, it says that I need to use 'aws-sdk'.
In controller I'm calling:
aws_object = AWS::S3::S3Object.find #component.folder.path, 'bucket-name'
send_data(aws_object.value, :type => #component.folder_content_type)
EDIT:
My model looks like:
attr_accessible :folder
has_attached_file :folder,
:path => ":rails_root/data/folders/:id/:basename.:extension",
:storage => :s3,
:s3_credentials => {
:bucket => "my-bucket-name",
:access_key_id => "XXXXXXXXX",
:secret_access_key => "XXXXXXXXX"
}

This worked for me:
http://trevorturk.com/2008/12/11/easy-upload-via-url-with-paperclip/
There's a example to download too.
The secret was ".read" :
data = open(asset.uploaded_file.url)
send_data data.read, :type => data.content_type, :x_sendfile => true,:filename => asset.file_name

Related

Rails 4 + Paperclip + Devise + S3: Images not uploading to S3?

I have an Active model (you can think of an Active as a User) that has authentication setup with Devise. I am trying to add a photograph attribute to my Active model and be able to upload pictures with S3.
Migration:
class AddAttachmentPhotographToActives < ActiveRecord::Migration
def self.up
change_table :actives do |t|
t.attachment :photograph
end
end
def self.down
drop_attached_file :actives, :photograph
end
end
Active model:
...
has_attached_file :photograph,
:styles => { :medium => "300x300>", :thumb => "100x100>" },
:storage => :s3,
:default_url => '/images/:attachment/missing_:style.png',
:path => "users/:id/photograph/:style.:extension",
:bucket => ... ,
:s3_credentials => {
:access_key_id => " ... ",
:secret_access_key => " ... "
}
Both config/environments/production.rb and config/environments/development.rb have the following:
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV[' ... '],
:access_key_id => ENV[' ... '],
:secret_access_key => ENV[' ... ']
}
}
I have my form for uploading a picture in views/devise/registrations/edit.html.erb like so: <%= f.file_field :photograph %>. However, after I select and update an Active with this form (the update goes through successfully), the path to my image (generated with <%= image_tag #active.photograph.url %>) is:
http://localhost:3000/images/photographs/missing_original.png
instead of an S3 address.
Also note I am using the following gems:
gem "paperclip", "~> 3.0"
gem 'aws-sdk'
I have never used S3 before, but after I select an image to upload and hit "enter" on my update page, my S3 bucket on the Amazon portal is still empty, so the update never went through.
Did I not set something up correctly?
Your code looks fine - are you sure you have S3 set up correctly?
Here is the code we use - hopefully this will help:
#app/models/image.rb
Class Image < ActiveRecord::Base
has_attached_file :image,
:styles => { :medium => "x300", :thumb => "x100" },
:default_url => "***********",
:storage => :s3,
:bucket => '*********',
:s3_credentials => S3_CREDENTIALS
end
#config/initializers/s3.rb
if Rails.env == "production"
# set credentials from ENV hash
S3_CREDENTIALS = { :access_key_id => ENV['S3_KEY'], :secret_access_key => ENV['S3_SECRET'], :bucket => "firststop"}
else
# get credentials from YML file
S3_CREDENTIALS = Rails.root.join("config/s3.yml")
end
#config/s3.yml
development:
access_key_id: **************
secret_access_key: ***************
bucket: *******
This works fine for us
Don't leave those keys in your code. At the minimum, place creds in config/environment.rb file:
S3_KEY='myKey'
S3_SECRET='mySecret'
#etc.
Then reference them in your code as S3_KEY, etc.
More on this and related methods: How do I store keys for API's in Rails?

Paperclip + AWS S3, Prefixing remote path with my local path

I'm using Paperclip with a Rails 4 app and Amazon S3 storage. On my development machine, the site is running at
/Users/Jeff/Sites/example.com/web
When I upload a file with Paperclip to S3, the remote path in S3 inherits my local folder structure.
http://s3.amazonaws.com/example_com_bucket/Users/Jeff/Sites/example.com/web/public/assets/uploads/my_class/8/medium/some_image.png?1383060287
Why is this happening? How do I strip that part out? I tried changing the :path property but that only seemed to affect the "application" part of the path (e.g. after /assets/uploads) My site is still in development, so I don't care about having to preserve links.
My config is...
config.paperclip_defaults = {
:storage => :s3,
:path => '/:class/:attachment/:id_partition/:style/:filename',
:s3_credentials => {
:bucket => 'example_com_bucket',
:access_key_id => '...',
:secret_access_key => '...'
}
}
I had this exact same issue when I was using the :url parameter where I should have been using the :path parameter:
has_attached_file :primary_photo,
:styles => ...,
:storage => :s3,
:s3_host_name => 's3-us-west-2.amazonaws.com',
:s3_credentials => 'config/s3.yml',
:url => '/product/:attachment/:id/:style/:filename'
I fixed it by changing my config to this:
has_attached_file :primary_photo,
:styles => ...,
:storage => :s3,
:s3_host_name => 's3-us-west-2.amazonaws.com',
:s3_credentials => 'config/s3.yml',
:path => '/product/:attachment/:id/:style/:filename'

Getting S3 Credentials from the database at startup in rails

Using a combination of the rails-settings gem and paperclip, I've got my application set up such that one can specify S3 credentials in the database (through an interface in the front end) and can then declare attachments like this;
class Asset < ActiveRecord::Base
has_attached_file :attachment,
:default_url => "content/no-img.jpg",
:s3_credentials => {
:access_key_id => Settings.AWS_ACCESS_KEY_ID,
:secret_access_key => Settings.AWS_SECRET_ACCESS_KEY
}
This works great, but this isn't the only type of attachment in the application (there are other things such as client logos). I'm finding that I need to specify the S3 credentials on every one. I've already tucked some of the defaults away in my app config file;
class Application < Rails::Application
#Paperclip Defaults
config.paperclip_defaults =
{
:storage => :s3,
:bucket => "my-bucket-name"
}
And this all works great, but if I try to pull down the username and password into the app config too, I get the following error;
ActiveRecord::ConnectionNotEstablished (ActiveRecord::ConnectionNotEstablished)
A fairly self explanatory error message, but how do I get around it? If I put the config in the environment files I get the same issue, and if I put them in an initializer like this;
#Paperclip Defaults
MyApp::Application.config.paperclip_defaults =
{
:storage => :s3,
:bucket => "my-bucket-name",
:s3_credentials => {
:access_key_id => RailsSettings::Settings.AWS_ACCESS_KEY_ID,
:secret_access_key => RailsSettings::Settings.AWS_SECRET_ACCESS_KEY
}
}
Then the values don't seem to get picked up and paperclip defaults back to storing the files in my local system directory. Could anyone advise on the best approach to handling this?
EDIT
So after re-reading the documentation I discovered "After Initializers", which gets around the whole active-record not being loaded issue. I have this in my app config;
config.after_initialize do
#Paperclip Defaults
config.paperclip_defaults =
{
:storage => :s3,
:bucket => "my-bucket-name",
:s3_credentials => {
:access_key_id => RailsSettings::Settings.AWS_ACCESS_KEY_ID,
:secret_access_key => RailsSettings::Settings.AWS_SECRET_ACCESS_KEY
}
}
end
And specify this in each model;
has_attached_file :attachment,
:default_url => "content/no-img.jpg",
:path => "#{Rails.env}/:client_name/#{DateTime.now.year}/:name/:basename/:basename-:style.:extension"
yet it still isn't picking up the defaults I specify (it still tries to put them in the public/system folder)
Right, sorted. If anyone has this issue, here's the solution (you basically need to use the "initializers" method to switch active record on before you set the config);
initializer "active_record.initialize_database" do |app|
app.config.paperclip_defaults =
{
:storage => :s3,
:bucket => "my-bucket-name",
:s3_credentials => {
:access_key_id => RailsSettings::Settings.AWS_ACCESS_KEY_ID,
:secret_access_key => RailsSettings::Settings.AWS_SECRET_ACCESS_KEY
}
}
end

Rails paperclip amazon aws s3 gem, how to change image url?

In my model I have:
has_attached_file :image,
:storage => :s3,
:styles => { :original => ["300x250>", :png], :small => ["165x138>", :png], :mini => ["120x120>", :png] },
:path => 'images/vind/:style/:id/:basename.:extension',
:url => 'images/vind/:style/:id/:basename.png',
:bucket => 'konkurrencerher',
:s3_credentials => {
:access_key_id => 'x',
:secret_access_key => 'x'
}
The problem is just that there is added the amazon s3 hostname to the url in view.
I have a solution to this, but is a bit ugly:
<%= image_tag(kon.photo.image.url(:small).gsub("http://s3.amazonaws.com/konkurrencerher", ""), :class => 'koni') %>
But, how is it possible to define the image url in the model, without the Amazon S3 hostname?
Take a look at Paperclip::Storage::S3, especially on the :s3_host_alias.
You can try configuring your has_attached_file with the following additional options
:url => ':s3_alias_url',
:s3_host_alias => "example.domain.net"
Hope this helps.
My solution created a file in the initializers map with this:
Paperclip.interpolates(:s3_path_url) { |attachment, style|
"#{(attachment.path).gsub("images/", "")}"
}
And then the url should be:
:url => ':s3_path_url'
This is a much better solution.

heroku+s3+paperclip

Guys,
I'm having a problem with s3...I'm trying to configure the s3 this way to work with the paperclip:
has_attached_file :photo,
:storage => :s3,
:bucket => 'gallerybucket',
:styles => { :small => ["150", :png], :large => ["500", :png], :very_large => ['750x500>', :png] },
:path => ":rails_root/public/images/:class/:attachment/:id/:style_:basename.png",
:url => "/images/:class/:attachment/:id/:style_:basename.png",
:default_url => "/images/sem_imagem.gif",
:s3_credentials => {
:access_key_id => ENV['ac'],
:secret_access_key => ENV['sc']
}
but it always shows me this error. I don't understand what I'm doing wrong here. Is there some configuration missing?
If you don't have an s3 account already go get one here:
http://aws.amazon.com/s3/
You need to add this to your contact model:
app/models/contact.rb
has_attached_file :picture,
:styles => {:large => "275x450>"},
:storage => :s3,
:s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
:path => "appname/:attachment/:style/:id.:extension"
Make sure you appname is your rails app name on heroku. And make sure you rename picture to whatever you have named your picture.
Then you need a config file in config/s3.yml.
development:
bucket: bucked_name
access_key_id: key
secret_access_key: secret
production:
bucket: bucked_name
access_key_id: key
secret_access_key: secret
Make sure you get the key and secret correct.
In your gem file make sure you have these gems install :
gem "aws-s3", :require => "aws/s3"
gem "paperclip"
Sounds like you added the variables to you heroku account, but did you add them to your .bashrc file?
export ACCESS_KEY_ID='acckeyid'
export SECRET_ACCESS_KEY='secacckey'
Then in your code:
:s3_credentials => {
:access_key_id => ENV['ACCESS_KEY_ID'],
:secret_access_key => ENV['SECRET_ACCESS_KEY']
}
I have a blog post I wrote that talks about this a little as well.

Resources