1. Saving files to a directory that is not shared between deploys or servers
If you save your uploads to a made up directory like "RAILS_ROOT/uploads"
, this directory goes away after every deploy (since every release gets a new). Also this directory is not shared between multiple application servers, so your uploads are randomly saved to one local filesystem or another. Fixing this afterwards is a lot of fun.
Only two folders are, by default, shared between our application servers and deployments: "RAILS_ROOT/storage"
and "RAILS_ROOT/public/system"
(note that this might be different if you are not
hosting at makandra
Show archive.org snapshot
).
2. Publishing confidential files to the whole Internet
All files in public/system
are publicly accessible and requests will not touch your Rails application. Users can usually download your entire file catalog by seeing one path like "public/system/images/4.jpg"
and then replacing the record ID (4
) with values from 1 to 9999999999.
So don't store confidential stuff in there. Non-public files should by default go into /storage
and should be delivered from a Rails controller action (e.g. /images/4/download
) by using send_file
. Since Rails code is doing the delivery you can do your usual authentication and authorization beforehand.
There are few exceptions where you want to store confidential files in the public
folder. E.g. you need to deliver many thumbnails for an image gallery and don't want to spawn 50 Rails processes to deliver the image. In that case you can store the images in public/system
but use for the path a non-guessable hash of e.g. the record ID and the application's secret token. So virtual paths need to look like "/public/system/images/5/ab4543fa3ecf44/image.jpg"
.
- For instructions for Paperclip see our card Deliver Paperclip attachments to authorized users only.
- For instructions for CarrierWave see our card Deliver Carrierwave attachments to authorized users only
3. Using the same storage folder for multiple Rails environments or test processes
This one affects your developers. If an image with ID 4 always ends up as public/system/images/4.jpg
, multiple Rails environments (e.g. development
and test
) will randomly see and overwrite each other's files. See Always store your Paperclip attachments in a separate folder per environment for instructions how to fix this in Paperclip. Apply similiar techniques to Carrierwave etc.
4. Ignoring existing files when changing your storage paths
When you change your applications (e.g. because you follow the advice in this post) you must migrate files that are already stored on your staging and production servers. If the application hasn't seen production yet, check with your client if you can simply wipe all images/documents/whatever. But don't display broken images, it's unprofessional und looks like you screwed up.
- For instructions how to migrate a complete folder structure, see our card Carrierwave: How to migrate to another folder structure:
5. Rails 2: Forgetting to add the multipart option to your upload form
When uploading files, you must set the multipart option like this in very old versions of Rails:
form_for @invoice, :html => { :multipart => true } do
If you do not, Rails will only receive the file name.