Gem CarrierWave
Bài đăng này đã không được cập nhật trong 9 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