Lưu trữ hình ảnh tới remote server trong Ruby on Rails với vsftpd
Bài đăng này đã không được cập nhật trong 3 năm
Khi phát triển một website chắc hẳn chúng ta quan tâm rất nhiều tới vấn đề tải lên và lưu trữ hình ảnh của người dùng.
Bài viết này mình trình bày một số cách thông thường để giải quyết vấn đề này. Trong qúa trình mình làm projects đã gặp phải một vài khúc mắc, do vậy mình ghi lại bài viết để tiện theo dõi cho lần sau và cũng giúp cho người mới bắt đầu như mình tiếp cận dễ hơn và rút ngắn thời gian tìm hiểu.
Để tài hình ảnh lên server, Rails cung cấp một vài thư viện cho chúng ta như:
Tùy từng sở thích mỗi người mà lựa chọn gem
riêng cho phần này. Mình sử dụng quen thuộc gem carrierwave
. Do vậy bài viết này mình sử dụng nó.
Đa số ứng dụng website đều lưu trữ hình ảnh, database và deploy code ở các server riêng để đảm bảo dễ quản lý, tăng cường bảo mật hay tăng hiệu suất hoạt động hơn cũng như giảm thiểu rủi ro hơn khi dùng chung server.
Về phần kết nối vào database server mình đã có viết một bài rồi, mọi người có thể tham khảo ở link sau Kết nối với Database trong Rails
Bài này mình trình bày về phần tải hình ảnh lên server.
Upload lên server lưu trữ hình ảnh riêng
Để upload hình ảnh cũng như tệp tin khác lên remote server mình sử dụng FTP
. Trong ubuntu có gói phần mềm là vsftpd
.
Chuẩn bị server để lưu trữ hình ảnh
Tạo người dùng mới (không nên sử dụng root
), mình ví dụ tạo người dùng tên là demo
.
$ ssh <remote_server>
root:~# adduser demo
password for `demo`
...
Tạo thư mục cho upload hình ảnh lên và gán quyền cho user.
:~# cd /home/demo/
:~# mkdir public_html/uploads -p
:~# chmod 755 public_html -R
:~# chown demo:demo public_html -R
Cài đặt và cấu hình vsftpd
server trên ubuntu.
ssh <remote server>
sudo apt-get install vsftpd
Mở file
cấu hình /etc/vsftpd.conf
và sửa một số dòng thông tin sau:
Việc đầu tiên cần làm là tắt quyền truy cập của anonymous
user bằng cách thay đổi anonymous_enable
từ yes
sang no
anonymous_enable=NO
Thứ 2 cần cấp quyền tạo và ghi thư mục
bỏ comment trước local_enable
và chuyển giá trị từ NO
sang YES
local_enable=YES
write_enable=YES
Với cấu hình như trên thì khi demo
user đã có thể upload được hình ảnh cũng như tệp tin lên server rồi.
Tuy nhiên khi upload lên thì hình ảnh sẽ chịu tác động tổng hợp từ quyền cơ bản (777)
với thư mục và (666)
đối vơi file và một gía trị cấu hình local umask
của server ftp
.
Gía trị mặc định local_umask
của vsftpd
là 077
.
Chúng ta cùng tìm hiểu về umask
.
The user file-creation mode mask (umask) - đó là xác định quyền của tệp tin khi mới được tạo ra.
Quyền cơ bản của file
là 0666 (hay 666) và thư mục là 0777 (hay 777).
Như vậy file và thư mục khi mới tạo ra sẽ chịu tác động tổng hợp từ base permission
trên và gía trị local_umask
.
Vậy cách tính quyền file và thư mục khi mới tạo ra từ 2 quyền kia như thế nào?
`quyền mới file or folder` = `base permisstion` - `local_umask`
Ví dụ khi ta set local_umask
= 002 thì:
File được tạo ra sẽ có quyền là: 666 - 002 = 664.
Folder được tạo ra có quyền là: 777 - 002 = 775.
Với gía trị mặc định local_umask
của vsftpd
là 077
, vậy file được tạo ra có quyền là 600
. Do vậy khi upload hình ảnh lên server người dùng sẽ không thể xem được.
Do vậy chúng ta nên đặt local_umask
là 002
hoặc 022
.
Tìm kiếm tới dòng sau trong file cấu hình vsftpd
và sửa lại thành như sau:
local_umask = 022
Khởi động lại vsftpd
server.
service vsftpd restart
Cấu hình rails app
của bạn
Chúng ta sử dụng gem
sau để upload lên server đã cấu hình ở phía trên dùng ftp
server.
https://github.com/luan/carrierwave-ftp
Thêm dòng sau vào Gemfile
gem 'carrierwave-ftp', :require => 'carrierwave/storage/ftp/all' # both FTP/SFTP
gem 'mini_magick', '3.8.0'
gem 'carrierwave', '0.10.0'
Chạy bundle install --without production
để cài đặt.
Tạo file
config/initializes/carrierwave.rb
với thông tin như sau:
CarrierWave.configure do |config|
config.ftp_host = ENV['ftp_host']
config.ftp_user = ENV['ftp_user']
config.ftp_passwd = ENV['ftp_passwd']
config.ftp_folder = "/public_html"
config.ftp_url = ENV['ftp_url']
config.ftp_passive = true
end
Chú ý cần export
các biến environments
ở trên heroku
.
Tiếp theo là cấu hình carrierwave
Ở đây mình sử dụng carrierwave
và tạo một uploader tên là pictures_uploader.rb
có nội dung như sau:
class PictureUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
if Rails.env.production?
storage :ftp
else
storage :file
end
version :medium do
process resize_to_fill: [480, 360]
end
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def extension_white_list
%w(jpg jpeg gif png)
end
end
Vậy là đã xong cấu hình cho phép user upload hình ảnh lên server remote rồi.
All rights reserved