📦carrierwaveuploader / carrierwave
← 返回首页
Classier solution for file uploads for Rails, Sinatra and other Ruby web frameworks
🌐 github.com📅 创建于 2008-08-28🔄 更新于 2026-10-12

📄 仓库 README

在 GitHub 查看 ↗
来自 GitHub 仓库自述文件 · 版权归原作者所有

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.

Supported Ruby and Rails versions

Each release is tested against the versions below. The gemspec only states a minimum, so Bundler will happily install an old CarrierWave alongside a Rails newer than it has ever seen — which is how a patch-level upgrade ends up failing at boot. Check this table when upgrading Rails.

CarrierWave Rails Ruby
4.0 7.0 – 8.1 >= 2.7
3.1 6.0 – 8.0 >= 2.5
3.0 6.0 – 7.1 >= 2.5
2.2 5.0 – 6.1 >= 2.2.2

Only the latest release gets fixes; older lines are listed so you can tell whether your combination was ever supported.

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.

Leave the column nullable: NULL is what it holds when no file is mounted, so a default: [] or null: false on it doesn't hold — the NULL is written on save. The uploader's own readers answer an empty array either way, and are what to read:

user.avatars             # => [] when there is no file
user.avatars_identifiers # => []
user[:avatars]           # => nil, the column as it is stored

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.

With the :file storage, 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

The name is worked out again whenever the stored file is located, so it has to come out the same every time. Memoise anything that would otherwise differ per call, in an instance variable of your own, as @filename is the uploader's:

def filename
  @stable_filename ||= "#{SecureRandom.uuid}.#{file.extension}"
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-

📈 近 7 天 Star 趋势

每日新增 Star(柱)与累计 Star(线)· 数据来自 GitHub

🏆 排名变化趋势

在各榜单中的排名历史(数字越小越靠前)

📋 历史上榜记录

每次快照的详细数据
日期 榜单 排名 周期新增 总 STAR