May 26, 2011

Paperclip + S3 with Rails

When I revamped my portfolio, one of the major changes I did was to change my attachment process to upload files (screenshots of my projects, etc) to Amazon S3 instead of to the local filesystem.

Why S3?

Putting large media files on S3 (aka "content storage/distribution") is a great idea because:

  1. You don't have to use up large amounts of storage on your web hosting plan, and S3 is super cheap. Even if you have an unlimited storage plan or aren't worried about using it up, this is still good idea because your files are all stored externally so you don't have to worry about backing them up or moving them if you want to switch hosts later (like I did).

  2. Amazon S3 is cheap (can you say "less than five cents a month"?), fast, scalable, and reliable. And probably many more nice things that I'm forgetting.

  3. Rails is slow, and going through the application stack to pull images all the time is slow.

Now that I've convinced you, I'm going to show you how incredibly easy it is to have your uploads upload directly to S3 with the help of a handy plugin called Paperclip.

Uploads with Paperclip

Note, this is assuming that you are already using Paperclip in your app for your file attachment service. To do that, there's a great Quick Start guide here.

First, add the aws-s3 gem in your Gemfile (you are using Rails3's bundler, aren't you? If not, get started):

gem 'aws-s3', :require => 'aws/s3'

Next, create a file called s3.yml in your config/ directory (where database.yml lives as well):

access_key_id: [YOUR AWS ACCESS KEY]
secret_access_key: [YOUR AWS SECRET KEY]

In whatever model you created for the uploaded object(s), for instance mine is Photo, add the following parameters to the usual Paperclip command like so:

has_attached_file :photo,
                  :storage => :s3,
                  :s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
                  :s3_permissions => "public-read",
                  :path => ":filename",
                  :bucket => [YOUR S3 BUCKET NAME]

And that's it! Now whenever you upload files via Paperclip, the files will be automatically uploaded to the proper S3 bucket and the resource URL will point to the S3 static url.

Have fun uploading!