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
Related
I'm working on a Rails website that uses Paperclip to upload files to Amazon S3 and then serve them through Cloudfront. I've got the uploading working fine, and Cloudfront is serving the files properly, but for some reason ModelObj.attachment.url isn't working properly on my production server. It works fine on my development server (WEBrick under Windows 8) but is returning the wrong URL on the live site (LAMP with Phusion Passenger). It returns almost the right url, but instead of
http://[stuff].cloudfront.net/kidbooks/snds/5072_original.mp3?1393858446
I'm getting
http:///kidbooks/snds/5072_original.mp3?1393858446
It's configured as follows: In environment.rb:
Paperclip::Attachment.default_options.merge!({
:storage => :s3,
:bucket => APP_CONFIG['s3_bucket'],
:path => "/#{APP_CONFIG['s3_path']}/:attachment/:id_:style.:extension",
:s3_credentials => {
...
}
})
And in the model:
has_attached_file :snd,
:url => ':s3_alias_url',
:s3_host_alias => APP_CONFIG['cloudfront_domain']
APP_CONFIG is being set properly on both servers; I've checked. (Or at least, it's being set properly in the console on the live server; I guess I could check more directly. There doesn't appear to be anything relevant in environments/development.rb or production.rb. What's going wrong here, and how can I fix it?
(I found this question, which is close to what I need, but only involves S3.)
Update: Found something weird. Model.snd.options returns a hash that includes, among other things, :s3_host_alias=>nil. Maybe my model is somehow being loaded before my configuration files?
Aha, found it. For some reason my model is either being loaded before my config files, or the loader doesn't have access to APP_CONFIG. This meant that :s3_host_alias was being set to nil, which of course broke things. I moved :s3_host_alias => APP_CONFIG['cloudfront_domain'] from the model to environment.rb, and now it's working fine.
I have no idea why my model would be loading before my config files, though.
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.
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
I am in the process of upgrading my rails app from 2.3 to 3.2, and I am having a problem with paperclip. My app was previously using paperclip v2.3.5 and now I am using rails 3.0.20 with paperclip v3.3.1
The problem happens when I try to upload an avatar to S3. It looks like paperclip is escaping the path before sending it to S3, but when I ask for the url of a specific style, the url uses an unescaped version of the path, and this leads to a "NoSuchKey" error from S3 (more like a 404 not found)
In my model I have
Paperclip.interpolates :last_modified do |attachment, style|
attachment.instance.updated_at.to_i
end
:path => "folder/:id/:style.:extension?:last_modified",
:url => ":s3_domain_url",
So the old version of my app was using urls from S3 like:
http://my-bucket.s3.amazonaws.com/folder/123/thumbnail.png?123456789
But now, everytime I upload an avatar, S3 will store the url like this:
http://my-bucket.s3.amazonaws.com/folder/123/thumbnail.png%3F123456789
and asking my model for the url of thumbnail style, will return:
http://my-bucket.s3.amazonaws.com/folder/123/thumbnail.png?123456789
which S3 can't find.
I know it seems to be an easy to fix issue, but my main concern is that the production app has a lot of users with many pictures and updating all of their images is a delicate task, and manually escaping the question mark is not a solution.
I just figured out how to fix a problem that was similar to this. There is a new escape_url option. Maybe try turning that to false?
:path => "folder/:id/:style.:extension?:last_modified",
:url => ":s3_domain_url",
:escape_url => false
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.