Paperclip - Upload to different S3 URLs from Different models - ruby-on-rails

I had a model from which I used paperclip and stored to S3.
In paperclip.rb
bucket_name = (Rails.env != 'production') ? "mcds_staging_fulltext" : 'mcds_fulltext'
Paperclip::Attachment.default_options.merge!({
storage: :s3,
s3_credentials: {
bucket: bucket_name
},
url: "#{CUSTOMER}/static_cover_images/:style/:basename.:extension",
path: "#{CUSTOMER}/static_cover_images/:style/:basename.:extension"
})
model1.rb
has_attached_file :cover_image, styles: { :original => ["100%"], :thumbnail => ["100*100", :png] }
validates_attachment_content_type :cover_image, content_type: /\Aimage\/.*\Z/, message: 'Invalid Content Type. Please upload jpg/jpeg/png/gif'
validates_attachment_size :cover_image, :in => 0.megabytes..5.megabytes, :message => 'must be smaller than 5 MB'
this works poperly and store my images in S3 in correct location.
Now I have another model from where I need to upload a paperclip attachment to a different S3 Location.
In model2.rb
has_attached_file :xslt
Paperclip::Attachment.default_options.merge!({url: "#{CUSTOMER}/xslts/:style/:basename.:extension"})
validates_attachment_content_type :xslt, content_type: "application/xslt+xml", message: 'Invalid Content Type. Please upload jpg/jpeg/png/gif'
validates_attachment_size :xslt, :in => 0.megabytes..5.megabytes, :message => 'must be smaller than 5 MB'
but this attachment still stores to my model1 S3 and not in the url specified in model2.
What am I doing wrong?

I completely removed paper_clip.rb file and added paper_clip configurations in therespective models.
model1:
has_attached_file :file1,
storage: :s3,
s3_credentials: {
bucket: bucket_name
},
url: "#{CUSTOMER}/cover_images/:style/:basename.:extension",
path: "#{CUSTOMER}/cover_images/:style/:basename.:extension"
model2:
has_attached_file :file2,
storage: :s3,
s3_credentials: {
bucket: bucket_name
},
url: "#{CUSTOMER}/file2_folder/:style/:basename.:extension",
path: "#{CUSTOMER}/file2_folder/:style/:basename.:extension"
this stores theattachment correctly in differen S3 folders.

Related

Paperclip does not show image but instead shows title with amazon s3 in rails?

I am using paperclip and amazon s3 to store images for my website. Everything is working correctly without s3 in development mode but when I try to use s3 it shows me the title of the image and not the image. I have copied what is in the heroku guide https://devcenter.heroku.com/articles/paperclip-s3.
This is the gemfile
gem 'paperclip'
gem 'aws-sdk', '~> 2.3'
this is in profile.rb in class profile
has_attached_file :avatar,
:styles => { :medium => "300x300>", :thumb => "100x100>" },
:default_url => ":style/missing.jpg"
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
this is in production.rb
config.paperclip_defaults = {
storage: :s3,
s3_host_name: "s3-#{ENV['AWS_REGION']}.amazonaws.com",
:s3_protocol => :https,
s3_credentials: {
bucket: ENV.fetch('S3_BUCKET_NAME'),
access_key_id: ENV.fetch('AWS_ACCESS_KEY_ID'),
secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY'),
s3_region: ENV.fetch('AWS_REGION'),
}
}
views
<%= image_tag #user.profile.avatar.url(:medium) %>
i have copied the heroku guide and added the host name and s3 protocol bit. whats wrong here?
I have followed the heroku guide and was successfully able to upload the user image to S3 using paperclip in development env and I can also see the image in users's profile.
My Gemfile:
gem 'paperclip'
gem 'aws-sdk-s3'
My development.rb
config.paperclip_defaults = {
storage: :s3,
s3_host_name: "s3.#{ENV['AWS_REGION']}.amazonaws.com",
s3_protocol: :https,
s3_credentials: {
bucket: ENV.fetch('S3_BUCKET_NAME'),
access_key_id: ENV.fetch('AWS_ACCESS_KEY_ID'),
secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY'),
s3_region: ENV.fetch('AWS_REGION'),
}
}
you have this (this might have caused an issue):
s3_host_name: "s3-#{ENV['AWS_REGION']}.amazonaws.com",
I have this (a dot after s3):
s3_host_name: "s3.#{ENV['AWS_REGION']}.amazonaws.com",
My user.rb is same as yours
has_attached_file :avatar,
:styles => { :medium => "300x300>", :thumb => "100x100>" },
:default_url => ":style/missing.jpg"
# Validate the attached image is image/jpg, image/png, etc
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
My show.html.erb
<%= image_tag #user.avatar.url(:medium) %>
I am using rails 5.2 version and with above code it works for me. Also do check whether your S3 bucket has public access to objects.

I Can upload images but cannot view them.(Paperclip S3 )

I uploaded images to Amazon S3, but they're not displaying.
Image can upload but cannot view them.
I am using rails5.2 , ruby 2.4
where i get the solution for this ?
Model.rb
has_attached_file :avatar,
styles: { medium: '400x400#' },
storage: :s3,
s3_credentials: "#{Rails.root}/config/s3.yml",
url: ":s3_domain_url",
path: "/uploaded_data/:class/:id/:basename.:extension",
s3_protocol: 'https'
view
<%= image_tag #product.avatar.url %>

Paperclip, S3, Rails—Aws::S3::Errors::InvalidArgument ():

As the title suggests, I'm using paperclip and S3 with Rails. When I try to create a record that has an image, I get this error:
[paperclip] saving interactives/5/images/original/Havaneser_Anton.jpg
(6.6ms) ROLLBACK
Completed 500 Internal Server Error in 2021ms (ActiveRecord: 86.8ms)
Aws::S3::Errors::InvalidArgument ():
I don't know what's going on, other than "It's not working"...
Here is my development.rb configuration:
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.
config.paperclip_defaults = {
storage: :s3,
s3_permissions: :public,
s3_region: ENV['AWS_REGION'],
s3_credentials: {
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
bucket: ENV['AWS_S3_BUCKET']
},
s3_protocol: 'https',
s3_host_name: "s3-#{ENV['AWS_REGION']}.amazonaws.com",
path: ":class/:id/:attachment/:style/:filename"
}
My Model looks like this:
class Interactive < ApplicationRecord
belongs_to :project
has_attached_file :image, styles: { low_res: "10%", medium: "300x300>", thumb: "300x250>" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :image, content_type: /\Aimage\/.*\z/
Check your s3_permissions: :public, the value for this option should be one of the "Canned ACL" permissions from here. :public does not appear to be an option!

Custom URL with Paperclip and AWS S3

We're using Paperclip with the aws-sdk gem to store and display images in our Rails app:
class User < ActiveRecord::Base
has_attached_file :image,
storage: :s3,
s3_credentials: 'config/s3.yml',
s3_protocol: :https,
styles: {
curriculum: '120x120>',
medium: '600x600>',
thumb: '200x200>'
},
default_url: 'missing_photo.png'
end
If I then use <%= image_tag current_user.image.url %> in an html.erb file, I get the following HTML: <img src="https://s3.amazonaws.com/<my_bucket>/users/images/000/000/001/medium/my_image.png?1419989041">.
How do I get that https://s3.amazonaws.com/<my_bucket> to be a custom URL like https://example.com? I have my domain all setup in Cloudfront along with its SSL certificate.
I looked up in the Paperclip S3 Storage documentation. There's a :url option, but nothing I write for that option seems to work.
I just ran across this problem and here are the settings I had to use
:s3_host_alias => "s3.example.com",
:url => ":s3_alias_url",
:path => ":class/:attachment/:id.:style.:extension"
From this link, I learned that, in addition to :s3_host_alias and :url, you have to specify path so you don't get
Paperclip::InfiniteInterpolationError
Kinda works out well because the default paperclip path is kinda wonky anyways.
Update
I put together an example and was able to get it working with the following:
class User < ActiveRecord::Base
has_attached_file :profile_picture,
styles: { :medium => "300x300>", :thumb => "100x100>" },
path: 'users/:attachment/:style-:hash.:extension',
hash_secret: "94dfda08e2ed473257345563594dfda08e2ed473257345563594dfda08e2ed473257345563594dfda08e2ed4732573455635",
default_url: "/images/:style/missing.png",
storage: :s3,
s3_protocol: 'http',
url: ':s3_alias_url',
s3_host_alias: 'distro1234.cloudfront.net',
s3_credentials: {
access_key_id: 'access_id',
secret_access_key: 's3cr3tK3y!',
acl: 'private',
bucket: 'my-bucket',
bucket_url: 'https://my-bucket.s3.amazonaws.com',
}
validates_attachment_content_type :profile_picture, :content_type => /\Aimage\/.*\Z/
end
And the following Gemfile:
gem 'paperclip'
gem 'aws-sdk', '~> 1.5.7'
Rails console:
=> u.profile_picture.url
=> "http://distro1234.cloudfront.net/users/profile_pictures/original-95eb509f9c81a341945a5a65e59e81880a739d39.jpg?1429638820"
Try something like this:
has_attached_file :image,
storage: :s3,
s3_credentials: 'config/s3.yml',
s3_protocol: :https,
styles: {
curriculum: '120x120>',
medium: '600x600>',
thumb: '200x200>'
},
url: ':s3_alias_url',
s3_host_alias: 'example.com',
default_url: 'missing_photo.png'

Rails 4, Paperclip, Amazon S3 Config Amazon Path

I'm trying to configure the endpoint which is returned from paperclip when my object is successfully uploaded to Amazon's S3 service. The upload and everything is working correctly, but the URL that is being returned is incorrect for displaying the upload.
Right now, the url that is being returned is http://s3.amazonaws.com/path/to/my/items (as seen in the picture below).
Instead of s3.amazonaws.com, I would like the root to be specific to the bucket's location (e.g. s3-us-west-1.amazonaws.com/path/to/my/items)
Where should I try and configure a different url path (from s3.amazonaws.com to something else)? I've tried to add a url with the above path into my configuration file like:
#Paperclip Amazon S3
config.paperclip_defaults = {
:storage => :s3,
:url => "https://s3-us-west-1.amazonaws.com/",
:s3_credentials => {
:bucket => ENV['S3_BUCKET_NAME'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
Which did not appear to have any effect. Please advise on where I should be setting this option!
Thanks in advance!
If you're going to use S3, we've found that you have to include the S3 credentials in your actual model (not just the config files). Here's what we do:
Model
#Image Upload
Paperclip.options[:command_path] = 'C:\RailsInstaller\ImageMagick'
has_attached_file :image,
:styles => { :medium => "x300", :thumb => "x100" },
:default_url => "****",
:storage => :s3,
:bucket => '****',
:s3_credentials => S3_CREDENTIALS,
:url => "/:image/:id/:style/:basename.:extension",
:path => ":image/:id/:style/:basename.:extension"
config/application.rb
# Paperclip (for Amazon) (we use EU servers)
config.paperclip_defaults = {
:storage => :s3,
:s3_host_name => 's3-eu-west-1.amazonaws.com'
}
config/s3.yml
#Amazon AWS Config
development:
access_key_id: **********
secret_access_key: **************
bucket: ****
production:
access_key_id: ***********
secret_access_key: ***********
bucket: ****
Hope this helps?
I also had the same problem when migrating to Spree 2.2 and am still not sure how to solve it the correct way. It seems like Paperclip should have been updating the path from the configuration, but it isn't.
Lacking a better solution, I've overridden the Spree::Image class like this:
1 Spree::Image.class_eval do
2 has_attached_file :attachment,
3 styles: { mini: '48x48>', small: '100x100>', product: '240x240>', large: '600x600>' },
4 default_style: :product,
5 url: '/spree/products/:id/:style/:basename.:extension',
6 path: 'products/:id/:style/:basename.:extension',
7 convert_options: { all: '-strip -auto-orient -colorspace sRGB' }·
8 end
After some experimentation I have found that setting :s3_host_name globally suffices. I ended up with the same problem because I was setting :s3_region, which was being used by Paperclip (post-4.3.1, with aws-sdk 2) for storing attachments, but not when generating the URLs.
This may also be of interest to readers who end up on this problem: https://github.com/thoughtbot/paperclip/wiki/Restricting-Access-to-Objects-Stored-on-Amazon-S3

Resources