I Can upload images but cannot view them.(Paperclip S3 ) - ruby-on-rails

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 %>

Related

Paperclip - Upload to different S3 URLs from Different models

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.

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'

Paperclip cropping original image because of thumbnail

So what I'm trying to do is have a centrally cropped image for the thumbnail and then also have the original image untouched so I can click on the thumbnail and bring the user to the original image.
So inside my model I have:
has_attached_file :image,
default_url: "/assets/missing.png",
url: "s3_domain_url",
storage: :s3,
s3_credentials: "#{Rails.root}/config/aws-#{Rails.env}.yml",
s3_permissions: 'authenticated-read',
path: "/users/:id/images/:basename.:extension",
s3_server_side_encryption: :aes256,
styles: { thumb: "200x200#" }
def s3_url(style = nil, expires_in = 30.seconds)
if image.exists?
image.s3_object(style).url_for(:read, :secure => true, :expires => expires_in).to_s
else
"/assets/missing.png"
end
end
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
And then inside my HTML I've got: <%= link_to image_tag(#challenge.s3_url(:thumb)), #challenge.s3_url(:original) %>
This should allow for the user to click the thumbnail and then it should take them to the original image. But currently it has the correct cropped thumbnail and then when the user clicks it, it will take them to just a larger version of the cropped thumbnail, not the original image.
Is there any way to do what I want?
The issue is the same as this SO question. Basically, needed to add a :style into the path. Now it works correctly.
So it now looks like:
has_attached_file :image,
default_url: "/assets/missing.png",
url: "s3_domain_url",
storage: :s3,
s3_credentials: "#{Rails.root}/config/aws-#{Rails.env}.yml",
s3_permissions: 'authenticated-read',
path: "/users/:id/images/:style/:basename.:extension",
s3_server_side_encryption: :aes256,
styles: { thumb: "200x200#" }

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

Paperclip : wrong bucket being used from yml

This has worked before, or so I believe.
For some reason, in my development environment, and even staging, Paperclip is using my production bucket instead of the development bucket.
Here is the part of the user model that relates to it
has_attached_file :avatar,
storage: :s3,
s3_credentials: "#{Rails.root}/config/s3.yml",
s3_permissions: :private,
path: "/:style/:id/:filename",
s3_protocol: "https",
styles: { medium: "300x300#", thumb: "100x100#", icon: "26x26#" },
default_url: ":style/ico_missing_user.png"
And here, my yml file:
common: &common
access_key_id: <%= ENV['S3_KEY'] %>
secret_access_key: <%= ENV['S3_SECRET'] %>
development:
<<: *common
bucket: mydevbucket
staging:
<<: *common
bucket: mystagingbucket
production:
<<: *common
bucket: myprodbucket
What am i doing wrong ?
I added "load_config.rb" file to my initializers directory:
load_config.rb
S3_CONFIG = YAML.load_file("#{::Rails.root}/config/s3.yml")[Rails.env]
and started using S3_CONFIG instead of "#{Rails.root}/config/s3.yml"
has_attached_file :avatar,
storage: :s3,
s3_credentials: S3_CONFIG,
s3_permissions: :private,
path: "/:style/:id/:filename",
s3_protocol: "https",
styles: { medium: "300x300#", thumb: "100x100#", icon: "26x26#" },
default_url: ":style/ico_missing_user.png"
The solution above worked fine to set the bucket, but then I started having a problem with paperclip when uploading files, saying ECONN:Aborted.
The following is what i have understood to work :
has_attached_file :avatar,
storage: :s3,
:s3_credentials => "#{Rails.root}/config/s3.yml",
:bucket => ENV['S3_BUCKET'],
s3_permissions: :private,
path: "/:style/:id/:filename",
s3_protocol: "https",
styles: { medium: "300x300#", thumb: "100x100#", icon: "26x26#" },
default_url: ":style/ico_missing_user.png"
Notice I separated the bucket from the credentials. I did this inspired on the rdocs for paperclip, and on the following sample

Resources