SkillAgentSearch skills...

Carrierwave

Classier solution for file uploads for Rails, Sinatra and other Ruby web frameworks

Install / Use

/learn @carrierwaveuploader/Carrierwave
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

CarrierWave

This gem provides a simple and extremely flexible way to upload files from Ruby applications. It works well with Rack based web applications, such as Ruby on Rails.

Build Status Code Climate SemVer

Information

Getting Help

  • Please ask the community on Stack Overflow for help if you have any questions. Please do not post usage questions on the issue tracker.
  • Please report bugs on the issue tracker but read the "getting help" section in the wiki first.

Installation

Install the latest release:

$ gem install carrierwave

In Rails, add it to your Gemfile:

gem 'carrierwave', '~> 3.0'

Finally, restart the server to apply the changes.

Upgrading from 2.x or earlier

CarrierWave 3.0 comes with a change in the way of handling the file extension on conversion. This results in following issues if you use process convert: :format to change the file format:

  • If you have it on the uploader itself (not within a version), the file extension of the cached file will change. That means if you serve both CarrierWave 2.x and 3.x simultaneously on the same workload (e.g. using blue-green deployment), a cache file stored by 2.x can't be retrieved by 3.x and vice versa.
  • If you have it within a version, the file extension of the stored file will change. You need to perform #recreate_versions! to make it usable again.

To preserve the 2.x behavior, you can set force_extension false right after calling process convert: :format. See #2659 for the detail.

Getting Started

Start off by generating an uploader:

rails generate uploader Avatar

this should give you a file in:

app/uploaders/avatar_uploader.rb

Check out this file for some hints on how you can customize your uploader. It should look something like this:

class AvatarUploader < CarrierWave::Uploader::Base
  storage :file
end

You can use your uploader class to store and retrieve files like this:

uploader = AvatarUploader.new

uploader.store!(my_file)

uploader.retrieve_from_store!('my_file.png')

CarrierWave gives you a store for permanent storage, and a cache for temporary storage. You can use different stores, including filesystem and cloud storage.

Most of the time you are going to want to use CarrierWave together with an ORM. It is quite simple to mount uploaders on columns in your model, so you can simply assign files and get going:

ActiveRecord

Make sure you are loading CarrierWave after loading your ORM, otherwise you'll need to require the relevant extension manually, e.g.:

require 'carrierwave/orm/activerecord'

Add a string column to the model you want to mount the uploader by creating a migration:

rails g migration add_avatar_to_users avatar:string
rails db:migrate

Open your model file and mount the uploader:

class User < ApplicationRecord
  mount_uploader :avatar, AvatarUploader
end

Now you can cache files by assigning them to the attribute, they will automatically be stored when the record is saved.

u = User.new
u.avatar = params[:file] # Assign a file like this, or

# like this
File.open('somewhere') do |f|
  u.avatar = f
end

u.save!
u.avatar.url # => '/url/to/file.png'
u.avatar.current_path # => 'path/to/file.png'
u.avatar_identifier # => 'file.png'

Note: u.avatar will never return nil, even if there is no photo associated to it. To check if a photo was saved to the model, use u.avatar.file.nil? instead.

DataMapper, Mongoid, Sequel

Other ORM support has been extracted into separate gems:

There are more extensions listed in the wiki

Multiple file uploads

CarrierWave also has convenient support for multiple file upload fields.

ActiveRecord

Add a column which can store an array. This could be an array column or a JSON column for example. Your choice depends on what your database supports. For example, create a migration like this:

For databases with ActiveRecord json data type support (e.g. PostgreSQL, MySQL)

rails g migration add_avatars_to_users avatars:json
rails db:migrate

For database without ActiveRecord json data type support (e.g. SQLite)

rails g migration add_avatars_to_users avatars:string
rails db:migrate

Note: JSON datatype doesn't exists in SQLite adapter, that's why you can use a string datatype which will be serialized in model.

Open your model file and mount the uploader:

class User < ApplicationRecord
  mount_uploaders :avatars, AvatarUploader
  serialize :avatars, JSON # If you use SQLite, add this line.
end

Make sure that you mount the uploader with write (mount_uploaders) with s not (mount_uploader) in order to avoid errors when uploading multiple files

Make sure your file input fields are set up as multiple file fields. For example in Rails you'll want to do something like this:

<%= form.file_field :avatars, multiple: true %>

Also, make sure your upload controller permits the multiple file upload attribute, pointing to an empty array in a hash. For example:

params.require(:user).permit(:email, :first_name, :last_name, {avatars: []})

Now you can select multiple files in the upload dialog (e.g. SHIFT+SELECT), and they will automatically be stored when the record is saved.

u = User.new(params[:user])
u.save!
u.avatars[0].url # => '/url/to/file.png'
u.avatars[0].current_path # => 'path/to/file.png'
u.avatars[0].identifier # => 'file.png'

If you want to preserve existing files on uploading new one, you can go like:

<% user.avatars.each do |avatar| %>
  <%= hidden_field :user, :avatars, multiple: true, value: avatar.identifier %>
<% end %>
<%= form.file_field :avatars, multiple: true %>

Sorting avatars is supported as well by reordering hidden_field, an example using jQuery UI Sortable is available here.

Changing the storage directory

In order to change where uploaded files are put, just override the store_dir method:

class MyUploader < CarrierWave::Uploader::Base
  def store_dir
    'public/my/upload/directory'
  end
end

This works for the file storage as well as Amazon S3 and Rackspace Cloud Files. Define store_dir as nil if you'd like to store files at the root level.

If you store files outside the project root folder, you may want to define cache_dir in the same way:

class MyUploader < CarrierWave::Uploader::Base
  def cache_dir
    '/tmp/projectname-cache'
  end
end

Changing the filename

To change the filename of uploaded files, you can override #filename method in the uploader.

class MyUploader < CarrierWave::Uploader::Base
  def filename
    "image.#{file.extension}" # If you upload 'file.jpg', you'll get 'image.jpg'
  end
end

Some old documentations (like this) may instruct you to safeguard the filename value with if original_filename, but it's no longer necessary with CarrierWave 3.0 or later.

Securing uploads

Certain files might be dangerous if uploaded to the wrong location, such as PHP files or other script files. CarrierWave allows you to specify an allowlist of allowed extensions or content types.

If you're mounting the uploader, uploading a file with the wrong extension will make the record invalid instead. Otherwise, an error is raised.

class MyUploader < CarrierWave::Uploader::Base
  def extension_allowlist
    %w(jpg jpeg gif png)
  end
end

The same thing could be done using content types. Let's say we need an uploader that accepts only images. This can be done like this

class MyUploader < CarrierWave::Uploader::Base
  def content_type_allowlist
    /image\//
  end
end

You can use a denylist to reject content types. Let's say we need an uploader that reject JSON files. This can be done like this

class NoJsonUploader < CarrierWave::Uploader::Base
  def content_type_denylist
    ['application/text', 'application/json']
  end
end

CVE-2016-3714 (ImageTragick)

This version of CarrierWave has the ability to mitigate CVE-2016-3714. However, you MUST set a content_type_allowlist in your uploaders for this protection to be effective, and you MUST either disable ImageMagick's default SVG delegate or use the RSVG delegate for SVG processing.

A valid allowlist that will restrict your uploader to images only, and mitigate the CVE is:

class MyUploader < CarrierWave::Uploader::Base
  def content_type_allowlist
    [/image\//]
  end
end

WARNING:

View on GitHub
GitHub Stars8.8k
CategoryDevelopment
Updated5d ago
Forks1.7k

Languages

Ruby

Security Score

80/100

Audited on Mar 26, 2026

No findings