Upload files trong Rails
Xin chào các bạn, hôm nay mình làm mẫu chi tiết cách upload một file hình ảnh trong rails, và bằng cách làm tương tự như mình làm sau đây, các bạn hoàn toàn có thể upload bất kì loại file nào. Đầu tiên, bạn cần cài đặt gem attach, bằng cách thêm vào Gemfile, và sau đó chạy bundle install : ...
Xin chào các bạn, hôm nay mình làm mẫu chi tiết cách upload một file hình ảnh trong rails, và bằng cách làm tương tự như mình làm sau đây, các bạn hoàn toàn có thể upload bất kì loại file nào.
Đầu tiên, bạn cần cài đặt gem attach, bằng cách thêm vào Gemfile, và sau đó chạy bundle install:
gem 'attach', '~> 1.0.1'
$ bundle install
Giống như việc lưu trữ file trong cơ sở dữ liệu, chúng ta cần phải tạo các migration cho các bảng để lưu trữ nội dung file. Trước khi run migration db, bạn cần rake attach:install:migrations để tự động thêm các migration cần thiết cho db của bạn.
$ rake attach:install:migrations
$ rake db:migrate
Thêm danh sách các file bạn muốn thêm vào model:
class Post < ActiveRecord::Base attachment :cover_photo end
Chúng sẽ có reader và writer cho tệp đính kèm mà mình muốn được tải lên. Ví dụ:
post = Post.new # Đặt ảnh từ dữ liệu chúng ta có post.cover_photo = some_binary_data post.cover_photo.file_name = "cover-photo.jpg" post.cover_photo.file_type = "image/jpg" # Hoặc chúng ta dùng ActionDispatch::Http::UploadedFile post.cover_photo = params[:person][:cover_photo] # Hoặc có thể dùng đối tượng pre-constructed `Attach::File` file = Attach::File.new(binary) file.name = "cover-photo.jpg" file.type = "image/jpg" post.cover_photo = file
Cần chú ý rằng khi chúng ta gọi reader sẽ luôn trả về đối tượng Attach::Attachment bất kể bạn đưa vào dữ liệu gì. Nếu chúng ta đưa vào một tệp đã được tải lên thì dữ liệu đó sẽ được chuyển sang đối tượng Attach::Attachment tại điểm mà dữ liệu được đặt.
Tiếp theo, cần cho phép tải các tệp lên server bằng cách thêm các trường cho form post, trước hết ta thêm một file_field:
<% form_for @post do |f| %> <%= f.label :cover_photo %> <%= f.file_field :cover_photo %> <% end %>
Để đảm bảo tham số cover_photo được cho phép sử dụng trong controller, ta cần thêm cover_photo attribute vào trong dòng params.require(:post).permit(...), ví dụ như sau:
params.require(:post).permit(:title, :content, :cover_photo)
Có rất nhiều cách để truy cập vào các file đã tải lên trên server, đơn giản nhất là buil-in middleware để chứa các tệp đính kèm. Giả sử ta đang cần upload ảnh bìa cho một bài post, và giờ cần show ảnh bìa đó. Mở file view của action show và chèn thẻ image như sau:
<% if @post.cover_photo %> <%= image_tag @post.cover_photo.url %> <% end %>
Phương thức url sẽ trả về một đường dẫn, mà sau đó middleware sẽ chặn và hiển thị tệp mà bạn đã chọn. Mặc định nó sẽ có dạng /attachment/736a33aa-e1b2-453e-808c-5a668e6e2fa3/photo.jpg. Nếu bạn tải lên một file không phải hình ảnh, bạn có thể muốn liên kết đến tệp này thay vì hiển thị chúng lên trình duyệt:
<%= link_to "Download product datasheet", @product.datasheet.url %>
Hiện tại, bạn có thể tải lên bật kì một file nào, tuy nhiên ta cần thêm một số validation để đảm bảo tệp tải lên trông giống hình ảnh. Mở Post model và thêm các thông tin sau:
class Post < ActiveRecord::Base attachment :cover_photo do validator do |attachment, errors| unless attachment.file_type =~ /Aimage/(jpeg|png|gif)/ errors << "must have an image content type" end end end end
Có 2 cách để có thể xóa tệp đính kèm, đơn giản nhất là gọi phương thức destroy.
def delete_cover_photo post = Post.find(params[:id] post.cover_photo.destroy end
Ngoài ra, bạn có thể sử dụng checkbox trên form của mình để gửi yêu cầu xóa tệp đính kèm. Để thực hiện điều này, chúng ta cần thêm một checkbox vào form cho thích hợp:
<% if f.object.cover_photo %> <%= f.check_box :cover_photo_delete %> <%= f.label :cover_photo_delete, "Delete cover photo?" %> <% end %>
Bạn cũng cần thêm cover_photo_delete vào danh sách các tham số được phép trong controller của bạn.
params.require(:post).permit(:title, :content, :cover_photo_delete)
Giờ hãy thử mở form và xóa ảnh của một bài đăng bạn đã lưu để thử kiểm tra nhé!
Vậy là qua bài viết, chúng ta đã biết thêm một cách upload hình ảnh (có thể dùng cho các loại tệp khác không phải hình ảnh) đơn giản trong rails. Cảm ơn các bạn đã quan tâm bài viết ! Xem thêm:
Follow the next tutorial about resizing images
Read more about the Attach gem
https://atech.blog/atech/file-attachments-in-rails-tutorial