paperclip doesn't create thumbnails on heroku - ruby-on-rails

I've been trying to get paperclip to upload images to amazon s3, but all I get is the original file being uploaded. No thumbnails are generated. My model has this in it:
has_attached_file :screenshot, :styles => {
:thumb => "100x80>",
:medium => "195x150>",
:large => "390x300>"
},
:storage => :s3,
:s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
:path => ":attachment/:id/:style.:extension"
The original file is in fact uploaded, but none of thumbnails appear. If I copy the src of a thumb format image, for instance, I get
<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Key>screenshots/8/thumb.png</Key>
<RequestId>B8A408560070E836</RequestId>
−
<HostId>
HAHUCuNxGKVDvqE3GnhGT1RcBgFGUxa35kqXmyRE+ii60DJS6r22ChDr22cOeCea
</HostId>
</Error>
This is running on heroku, which forces me to use a service like amazon. Not a problem but all the documentation I can find makes this look straightforward. I can't find any dependencies (bundler is happy), and I've been using AWS for 2 years now, without these problems, on another site, with a different bucket on the same account. Is it a problem of connecting the bucket to the account? I'm using the same credentials as in the other site. Only the bucket changes.
A couple more things. The directories that are being created in the path of the image that is being uploaded are permissions 000 or whatever the aws equivalent is. Nobody is permitted to do anything.
using Rails 3.

I had the same problem and the answer lies in:
:path => ":attachment/:id/:style.:extension"
Instead of storing the images in the same folder_id with different names, use the same name for the image and use the style for folders. The above would translate into:
:path => ":attachment/:id/:style/:filename"
So instead of trying to generate something like:
avatars/13/thumb.png
avatars/13/medium.png
avatars/13/large.png
You get this:
avatars/13/thumb/my_pic.png
avatars/13/medium/my_pic.png
avatars/13/large/my_pic.png

I installed paperclip as a plugin, and everything works.
Don't forget to remove the gem from your Gemfile.

Related

How to use Amazon S3 on Spree-2-2-stable

I need to configure my images on Amazon S3, but when I tried to do so under version 2-2-stable from Spree, I realized that this configuration were moved away from the admin panel.
I read somewhere that this configuration was creating some problems, and thus it was removed on 2-2. But I assume that the functionality is still working somehow.
When I try to add these configs to my config/initialize/spree.rb, I´m getting an error because these preferences are no longer existing.
preference :s3_access_key, :string
preference :s3_bucket, :string
preference :s3_secret, :string
These preferences are found on 2-1-stable but not on 2-2-stable
https://github.com/spree/spree/blob/2-1-stable/core/app/models/spree/app_configuration.rb
https://github.com/spree/spree/blob/2-2-stable/core/app/models/spree/app_configuration.rb
Is there any way how to get it working in order to use it together with Heroku?
Here is Spree's commit with the changes and some instruction as to how to make configuration changes.
https://github.com/spree/spree/commit/b1d6c5e4b9801d888cc76c05116b814945122207
My understanding is that you can still use paperclip to manage uploading to S3, which I have successfully done using their instructions. I have however had problems getting the save path on S3 to configure correctly. This might get you started ... in an environment config file put the following:
# Paperclip configs
config.paperclip_defaults = {
:storage => :s3,
:bucket => ENV['S3_BUCKET_NAME'],
:s3_credentials => {
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
I use environment variables for the S3 credentials, so yours will most likely be different. This chunk of code has made uploading files to S3 work, like I said I just can't force a specific file path on upload. Hope that helps.
EDIT - ADDITIONAL INFO:
I added the following to the spree.rb initializer to define a custom upload path and a custom url path.
# S3 upload path and url path configuration
Spree::Image.attachment_definitions[:attachment][:path] = 'products/:id/:style/:basename.:extension'
Spree::Image.attachment_definitions[:attachment][:url] = 'products/:id/:style/:basename.:extension'
To change default upload sizes you can override the Spree image decorator model. So under app/models add a spree directory and add a file named image_decorator.rb. You can then control the sizes with the following:
Spree::Image.class_eval do
attachment_definitions[:attachment][:styles] = {
:mini => '48x48>', # thumbs under image
:small => '350x700>', # images on category view
:product => '1024x768>', # full product image
:large => '600x600>' # light box image
}
end
Check out this page for specifics --> http://guides.spreecommerce.com/developer/logic.html
So to sum up, you can do all your general image/S3 configuration by updating your environment initializer, your Spree initializer and overriding the spree image_decorator model.

Broken images when seeding database on heroku

I have a Rails 4 application that uses paperclip to attach photos. My db/seeds.rb file adds some photos for my Person model with lines like this:
Person.create(:first_name => 'Jon', :last_name => 'Snow',
:photo => File.open("#{Rails.root}/app/assets/images/jon-snow.png))
In my app/models/person.rb file I have the :photo as a paperclip attachment where it is cropped and resized:
class Person < ActiveRecord::Base
has_attached_file :photo,
:styles => { :medium => "256x256#", :small => "64x64#", :tiny => "24x24#" },
:default_url => :set_default_avatar,
:url => "/assets/photos/:id/:style/:basename.:extension",
:path => ":rails_root/public/assets/photos/:id/:style/:basename.:extension"
validates_attachment_size :photo, :less_than => 5.megabytes
validates_attachment_content_type :photo, :content_type => ['image/jpeg', 'image/png']
My problem is that when I try to deploy this to heroku (with the Cedar stack) and then seed the database, the images all come up as broken. However, on my local computer everything comes up completely fine.
The broken image tag that is generated on heroku might look something like:
<img alt="Jon Snow" src="/assets/photos/21/small/jon-snow.png?1386825683">
Does anyone know why this link would break on heroku but not on my computer? I know that heroku is generating the resized photos because the heroku console outputs things similar to what is in this post: Seed images in heroku with paperclip.
However, it is putting them into public/assets instead of in public/assets/photos/:id/:style/:basename.:extension as the controller specifies.
I've tried doing what that linked post mentions, as well as running:
heroku run rake assets:precompile
and a number of other things, but nothing works. Any help would be greatly appreciated.
The issue is the same I described in this answer How to use paperclip with rails and how does it work in deployment?
The legacy Bamboo stack had a read-only file system so you were unable to write on the file-system.
In the new Cedar stack, the file system is no longer read-only, so the upload will not fail. However, you should keep using AWS or any other external storage because Heroku distributes your compiled application across several machines, and it's not guaranteed that the image will be visible from another request. They call it ephemeral filesystem.
In other words, you should keep using AWS or any other storage outside Heroku file-system.
From heroku-dev
The filesystem for the slug is read-only, which means you cannot
dynamically write to the filesystem for semi-permanent storage. The
following types of behaviors are not supported: Caching pages in the
public directory Saving uploaded assets to local disk (e.g. with
attachment_fu or paperclip)
Use AWS S3

Paperclip S3 - Can upload images but cannot view them

I'm created a Rails app running on Heroku, with Paperclip and S3. I've managed to upload images to my S3 bucket through the site (I can see them show up in my bucket on the Amazon control panel).
But when I add an Image tag i.e. <%= image_tag x.photo.url %>, I get the following html (tags omitted here), with no image displayed!
img alt="Test_tree" src="http://s3.amazonaws.com/hiphotos/ads/photos/000/000/015/original/test_tree.jpg?1344661020"
Why can't I see the images even though they're in the bucket?
Create a file a called paperclip initializer:
# config/initializers/paperclip.rb
# We are actually setting this to 's3_domain_url',
# so it's not a placeholder for something else.
Paperclip::Attachment.default_options[:url] = ':s3_domain_url'
Paperclip::Attachment.default_options[:path] = '/:class/:attachment/:id_partition/:style/:filename'
Or you could also place this inside production.rb:
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['S3_BUCKET_NAME'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
},
:url =>':s3_domain_url',
:path => '/:class/:attachment/:id_partition/:style/:filename',
}
Firstly, the url you are trying to use up there in your code is this:
http://s3.amazonaws.com/hiphotos/ads/photos/000/000/015/original/test_tree.jpg
When you visit that link in the browser, you see the following:
<message>
The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.
</Message>
<RequestId>810A6AE1D141304C</RequestId>
<Bucket>hiphotos</Bucket>
<HostId>
XXZ+s+slgZLsRWy5NiU/G0yAKBLftw0oT2dDKpas532qXJEPSrISVPqfZsEgpb2J
</HostId>
<Endpoint>hiphotos.s3.amazonaws.com</Endpoint>
So if we modify the url using the correct endpoint we get this:
http://hiphotos.s3.amazonaws.com/ads/photos/000/000/015/original/test_tree.jpg
Which does return the correct image.
If you are using European buckets, this can happen, and it might be the fault of the gem you are using to push things to s3.
There are loads of articles on how to get Paperclip, S3 and European buckets to play nicely together.
I have found though, that since I started using the asset_sync gem, which uses Fog instead of aws-s3 gem, I don't have any more trouble with paperclip and S3.
So I suspect Fog has something to do with making this problem go away for me. I'd recommend switching to it, if you're using something else.

Rails 3.2 Paperclip S3 Not Loading in Localhost

I just upgraded to Rails 3.2 and I'm using Amazon S3 with Paperclip to upload photos to my app.
Before my Image Urls would be:
http://s3.amazonaws.com/dealphotos.website.com/photos/428/large/Sandisk120Drive?1334754504
Now my Image Urls on Localhost are:
http://s3.amazonaws.com/dealphotos.website.com/deals/photos/000/000/428/large/Sandisk120Drive?1334754504
Notice the additional 000/000's - even if I take them out and visit the link it says:
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>"Long String of Numbers"</RequestId>
<HostId>
"Gives me a really long string of letters and numbers"
</HostId>
My Deal Model:
has_attached_file :photo, :styles => { :small =>"268x160>", :large =>"350x250>" },
:storage => :s3,
:bucket => 'dealphotos.website.com',
:s3_credentials => {
:access_key_id => ENV['S3_KEY_SPICY'],
:secret_access_key => ENV['S3_SECRET_SPICY']
}
And the images dont show up!
Before all I had to do was pull from Heroku and all my images and files would go to my development. What's going on?
You are most likely using the latest version of Paperclip (version >= 3).
Since this is a major version of paperclip there are documented incompatibilities with older versions of paperclip.
One MAJOR (and in my books good) change is that the default storage location of assets has changed.
Earlier it used to be /system/:attachment/:id/:style/:filename.:extension (from memory). This would be disastrous if you had 2 attachments with the same name (Company logo and Product logo) for example.
Now the new path used by paperclip is /system/:class/:attachment/:id_partition/:style/:filename.:extension
This means all your assets will be stored in the directory specified by above. :id_partitions are used so that the number of nodes (files/directories) in one directory doesnt exceed 1000.
I hope i've been able to explain the reason WHY you are seeing the problem. The default path has changed.
You have 2 options now -
Move old assets into the correct place in the new directory scheme (painful but recommended).
Move new assets into the old directory structure and add a :url + :path option in your attachment definition in the model to continue using the older scheme. (See https://github.com/thoughtbot/paperclip/blob/master/UPGRADING ).
Since it appears that you have images in BOTH the new structure and the old one. So no matter what you decide files will need to be moved from one structure to another. Unless the assets are bookmarked in some way, I suggest you move the older assets into the new directory structure.
Check out CarrierWave gem to file uploads. It works with 3.2 without any problems ;)
http://railscasts.com/episodes/253-carrierwave-file-uploads

How can I handle user-uploaded photo files for a Rails app (using paperclip) on Heroku?

So I'm making a Rails app which allows Users to create Items, and each Item has an image attachment, which is handled through the Paperclip gem. The Paperclip gem, by default, saves photos to the public folder, both in original (and thumbnail) form.
I can see how this can get out of hand pretty fast in terms of storage space, given that photos can be fairly big.
My questions:
1) How much space will Heroku allow me to hold for images in the public folder?
2) If Heroku only allows you to hold a finite amount of data in this folder (which I'm sure it does), how can I handle photo storage for a site that will probably have a lot of images? Remotely perhaps? Compression? (Specifics would be nice, as I am completely new to image storage.)
Heroku has a read-only file system for your app. Use Amazon S3 to store your uploaded images. Paperclip has great support for S3. Check out this Heroku guide.
As Chris said, you'll want to use a third party service like S3 and if you do end up using Paperclip then you'll eventually have something like this example in your model.
has_attached_file :photo,
:styles => { :thumb=> "100x100", :small => "300x300" },
:storage => :s3,
:s3_credentials => "#{Rails.root.to_s}/config/s3.yml",
:path => "/:id/:style/:filename"
And in your config directory you'll have an s3.yml credentials file that would look like:
development:
bucket: blahblah
access_key_id: sfoi40j8elkfv08hwo
secret_access_key: DJyWuRtsfoi40j8elkfv08hwos0m8qt
production:
bucket: blahblah
access_key_id: sfoi40j8elkfv08hwo
secret_access_key: DJyWusfoi40j8elkfv08hwos0m8qt

Resources