12/08/2018, 11:44
Gem CarrierWave
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. ...
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[:awidth] > 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