Gem CarrierWave
Bài đăng này đã không được cập nhật trong 10 năm
Nếu bạn muốn upload files một cách dễ dàng thì 1 giải pháp cho bạn là có thể sử dụng gem carrierWave. Gem này cung cấp một cách đơn giản và cực kỳ linh hoạt để upload các file từ từ các ứng dụng ruby. Sau đây chúng ta sẽ đi tìm hiểu về cách sử dụng gem carrierWave để upload files như thế nào
1. Cài đặt
Trong file Gemfile cần thêm vào
gem 'carrierwave'
Sau đó chạy bundle install để cài đặt và cuối cùng là restart lại server để nhận các thay đổi
2. Bắt đầu
Đầu tiên cần tạo 1 uploader, bạn có thể sử dụng rails để sinh ra nó
rails generate uploader Avatar
Sau khi chạy câu lệnh trên nó sẽ tạo ra file: app/uploaders/avatar_uploader.rb với nội dung file được tạo giống như sau
class AvatarUploader < CarrierWave::Uploader::Base
  storage :file
end
Bạn có thể sử dụng class uploader để lưu trữ và truy vấn dữ liệu như sau
uploader = AvatarUploader.new
uploader.store!(my_file)
uploader.retrieve_from_store!('my_file.png')
CarrierWave cung cấp cho bạn một store để lưu trữ lâu dài và một cache để lưu trữ tạm thời. Bạn có thể lựa chọn các store khác nhau, bao gồm cả filesystem và cloud storage
Active Record
Hãy chắc chắn rằng bạn đang load CarrierWave sau khi load ORM của bạn, nếu không bạn sẽ cần sử dụng require thủ công
require 'carrierwave/orm/activerecord'
Thêm một column vào model bằng cách tạo một migration
rails g migration add_avatar_to_users avatar:string
rake db:migrate
Mở file model của ban và thêm vào gắn kết uploader
class User < ActiveRecord::Base
  mount_uploader :avatar, AvatarUploader
end
Bây giờ bạn có thể gán file bạn muốn upload cho thuộc tính của user, chúng sẽ được tự động lưu trữ khi bản ghi được save
u = User.new
u.avatar = params[:file] # Assign a file like this, or
# like this
File.open('image_user1') 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'
3. Upload nhiều file
Chú ý: Bạn phải chỉ rõ sử dụng nhánh master để kích hoạt tính năng này
gem 'carrierwave', github: 'carrierwaveuploader/carrierwave'
Active record
Thêm một column để có thể lưu trữ một mảng. Nó có thể là một column mảng hoặc là column json. Bạn có thể tạo 1 migration như sau
rails g migration add_avatars_to_users avatars:json
rake db:migrate
Mở file model vừa tạo được và thêm vào uploader
class User < ActiveRecord::Base
  mount_uploaders :avatars, AvatarUploader
end
Hãy chắc chắn rằng các trường nhập file của bạn được cài đặt multiple. Ví dụ
<%= form.file_field :avatars, multiple: true %>
Và đảm bảo rằng controller upload của bạn cho phép thuộc tính upload nhiều file
params.require(:user).permit(:email, :first_name, :last_name, {avatars: []})
Bây giờ bạn có thể lựa chọn nhiều files trong dialog tải lên (có thể sử dụng tổ hợp phím SHIFT+SELECT), chúng sẽ được lưu tự động khi bản ghi được save
u = User.new(params[:user])
u.save!
u.avatars[0].url # => '/url/to/image.png'
u.avatars[0].current_path # => 'path/to/image.png'
u.avatars[0].identifier # => 'image.png'
4. Thay đổi thư mục lưu trữ
Để thay đổi nơi lưu trữ file được tải lên bạn chỉ cần ghi đè lên phương thức store_dir
class MyUploader < CarrierWave::Uploader::Base
  def store_dir
    'public/my/upload/directory'
  end
end
Nếu bạn lưu trữ các file bên ngoài thư mục gốc project, bạn có thể muốn định nghĩa cache_dir
class MyUploader < CarrierWave::Uploader::Base
  def cache_dir
    '/tmp/projectname-cache'
  end
end
5. Bảo vệ upload
Một số tập tin có thể gây nguy hại nếu tải lên sai vị trí, như các file php hoặc các file mã lệnh khác. CarrierWave cho phép bạn chỉ định một danh sách được cho phép. Nếu bạn đang gắn kết uploader, tải lên 1 file lỗi làm cho các bản ghi không hợp lệ. Nêu không một lỗi sẽ được sinh ra
class MyUploader < CarrierWave::Uploader::Base
  def extension_white_list
    %w(jpg jpeg gif png)
  end
end
6. Thêm versions
Thường thì bạn sẽ muốn thêm các versions khác nhau của 1 file. Ví dụ đơn giản là thu nhỏ hình ảnh. Để làm được điều này bạn cần phải cài đặt Imagemagick và MiniMagick để thay đổi kích thước của hình ảnh
class MyUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick
  process resize_to_fit: [800, 800]
  version :thumb do
    process resize_to_fill: [200,200]
  end
end
Khi upload bắt đầu, một image được tải lên và bạn muốn thay đổi kích thước của nó không vượt quá 800 x 800px. Một versions mới thumb được viết ra để thu nhỏ hình ảnh 200 x 200px. Ta có thể viết như sau
uploader = AvatarUploader.new
uploader.store!(image)                              # size: 1024x768
uploader.url # => '/url/to/image.png'               # size: 800x600
uploader.thumb.url # => '/url/to/thumb_image.png'   # size: 200x200
Bạn cũng có thể sử dụng các versions lồng nhau
class MyUploader < CarrierWave::Uploader::Base
  version :animal do
    version :human
    version :monkey
    version :llama
  end
end
Bạn cũng có thể thêm điều kiện cho các versions
class MyUploader < CarrierWave::Uploader::Base
  version :human, :if => :is_human?
  version :monkey, :if => :is_monkey?
  version :banner, :if => :is_landscape?
protected
  def is_human? picture
    model.can_program?(:ruby)
  end
  def is_monkey? picture
    model.favorite_food == 'banana'
  end
  def is_landscape? picture
    image = MiniMagick::Image.open(picture.path)
    image[:width] > image[:height]
  end
end
6. Cấu hình CarrierWave
CarrierWave có rất nhiều cấu hình mà bạn có thể tuỳ chọn, cho toàn bộ hoặc cho từng uploader
CarrierWave.configure do |config|
  config.permissions = 0666
  config.directory_permissions = 0777
  config.storage = :file
end
Hoặc là
class AvatarUploader < CarrierWave::Uploader::Base
  permissions 0777
end
Trong rails bạn cần khởi tạo cho nó
config/initializers/carrierwave.rb
7. sử dụng Amazon S3
fog được sử dụng để hỗ trợ Amazon S3. Bạn cần thêm nó vào trong Gemfile
gem "fog", "~> 1.3.1"
Bạn cần cung cấp fog_credentials và fog_directory của bạn trong initializer
CarrierWave.configure do |config|
  config.fog_credentials = {
    :provider               => 'AWS',                        # required
    :aws_access_key_id      => 'xxx',                        # required
    :aws_secret_access_key  => 'yyy',                        # required
    :region                 => 'eu-west-1',                  # optional, defaults to 'us-east-1'
    :host                   => 's3.example.com',             # optional, defaults to nil
    :endpoint               => 'https://s3.example.com:8080' # optional, defaults to nil
  }
  config.fog_directory  = 'name_of_directory'                     # required
  config.fog_public     = false                                   # optional, defaults to true
  config.fog_attributes = {'Cache-Control'=>'max-age=315576000'}  # optional, defaults to {}
end
Trong uploader bạn cần thiết lập storage cho :fog
class AvatarUploader < CarrierWave::Uploader::Base
  storage :fog
end
Bây giờ bạn có thể sử dụng phương thức CarrierWave::Uploader#url để trả lại url cho các file trên Amazon S3
Kết luận
Trên đây là những kiến thức cơ bản về gem CarrierWave. Do kiến thức hạn hẹp nên vẫn còn nhiều thiếu sót. Rất mong sự góp ý từ bạn đọc. Cảm ơn vì đã dành thời gian để theo dõi bài viết của tôi. Mong rằng nó có thể giúp ích cho bạn
All rights reserved
 
  
 