Everybody that has ever implemented file upload by hand in a Rails app knows that it’s no cakewalk, not to mention a major security risk. That’s why we use gems to handle file upload for us! But often it’s hard to decide which one to choose for your project.
There are three major file uploader gems in the Rails ecosystem, namely, Paperclip, CarrierWave and Refile. These gems upload and catalog files on the server, but we have come to expect much more from file uploaders.
- File caching: If a form fails to validate, we don’t want the user to pick his file again and reupload it. Therefore, file caching is necessary from a UX standpoint and it conserves bandwidth.
- Image processing: It should be able to resize and crop images to several different formats, and enable the developer to choose which library they will use to do so.
- File processing: This is a must if you want to extract EXIF data, create thumbnails for uploaded PDFs, PSDs, DOCXs, XLSXs...
- CDN & storage service support: A big plus as we want to keep bandwidth to our servers as low as possible and avoid possible data loss due to server failure.
- File streaming: Which keeps the server memory consumption low and lowers in-browser page render times.
- On-the-fly processing: Basically, it is the ability to process images and files on a per request basis. An interesting concept that enables developers to create content that adapts better to different situations.
- Clean code: Any gem that you use should never pollute your code and it should be easy to test!
Settings can be configured globally or on per model basis, which in turn puts a lot of logic that isn’t related to your model in your model. A side effect of this approach is that uploader logic can’t be tested independently of your model’s logic. And it basically has no file processing abilities. Ease-of-use and simplicity are Paperclip’s strong points.
When to use: It’s the go-to solution if you just need to upload a file and forget about it. It's also good enough when building simple APIs since they don't need file caching or processing. But it should be avoided in more complex applications.
CarrierWave is the Swiss army knife of Rails image uploaders.
It stores all uploader logic in uploader classes, which keeps your code clean, reusable and easy to test! Such code organization enables the definition of custom file processors which can use any kind of third party library, be it a gem or shell command.
It's most efficient when it comes to image processing as it lets you choose the order of processing files.
Files can be processed with many different processors and new processors can be defined. These processors are not only useful for creating images of different sizes, but they can also be used for extracting EXIF data, parsing uploaded text files, validating uploaded files... You are limited only by your imagination.
When to use: CarrierWave should be used in applications that are ‘image heavy’ or have logic associated with files that get uploaded.
Refile is the newest of the three, a successor to the ‘over-engineered’ CarrierWave, and strikingly similar to Dragonfly. It tries to combine the ease-of-use and simplicity of Paperclip with the power of CarrierWave. And falls short at doing that, at least in my opinion.
It has the ability to define custom file processors, but it processes all files on-the-fly. An interesting concept as it makes the gem basically unusable in production environments without a CDN and can be a potential vulnerability to DoS attacks.
It mounts as a separate Sinatra application on top of your Rails application, which enables it to stream files to improve page render times and conserve server memory.
Customization is a pain and testing isn’t the easiest task either as the application can’t tell you where it stored the file you gave it. On the other hand, it’s rapidly changing and has a lot of supporters.
When to use: In my opinion, on-the-fly image processors should be avoided as they have inherited DoS problems, no matter if your app uses a CDN or not. Refile should only be used if you absolutely need on-the-fly image resizing.
|Dynamic image resizing||No||No||Yes|
Choosing between CarrierWave, Paperclip and Refile can be difficult at times, but I would always recommend CarrierWave. It is the most powerful and customizable of the three. It keeps your code organized and clean, and is easy to test.
Refile isn't ready for prime time yet as it is still experiencing growth pains and has DoS issues, and Paperclip is fairly simplistic.