iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 27
1
自我挑戰組

關於 Ruby on Rails 的那些事系列 第 27

Day 27 - 上傳檔案 Carrierwave - 多個檔案

昨天說的是單一檔案上傳,如果要多個檔案上傳的話...

建立新欄位

資料表先新增可以儲存一個陣列的欄位。這個資料型態可以是 Array 或者 JSON。
不過選擇哪種資料型態會取決於你使用哪個資料庫。因為有些資料不支援 JSON( 例:SQLite )
有支援 JSON 格式的資料庫有 PostgreSQL、MySQL,建立專案時,已經設定過 database 為 PostgreSQL,所以這邊就用 JSON 格式來設定欄位型態:

$ rails g migration add_avatars_to_profiles avatars:json
$ rails db:migrate

沿用 uploader,但 model 要正確掛載

因為這次要上傳多個檔案,所以用複數,mount_uploaders、:avatars 都要加上 s

# app/models/profile.rb
class User < ActiveRecord::Base
  mount_uploaders :avatars, AvatarUploader
end

controller 設定通關條件

# profiles_controller.rb

def profile_params
  params.require(:profile).permit(:nickname, :email, {avatars: []})
end

請注意,多個檔案上傳,儲存的方式是陣列,所以在通過清洗的時候,要賦予一個空陣列的資料型態!
資料庫的table儲存的樣子:["apple.png", "orange.png", "banana.jpg"]

views 表單改為多選

<%= form.file_field :avatars, multiple: true %>

這樣就可以選取多個檔案!

如果要在上傳新檔案時,保留目前現有檔案的話,可以改成這段:


<% profile.avatars.each do |avatar| %>
  <%= hidden_field :profile, :avatars, multiple: true, value: avatar.identifier %>
<% end %>
<%= form.file_field :avatars, multiple: true %>

小補充:

profile.avatars[0].url
# 印出 '/url/to/file.jpg' 圖片的相對路徑

profile.avatars[0].current_path
# 印出 'path/to/file.jpg' 圖片的絕對路徑

profile.avatars[0].identifier
# 印出 'file.jpg' 圖片的檔名

profile.avatars[0].file.nil?
# 判斷檔案是否存在

限制檔案類型

為了避免有心人士或使用者不小心上傳錯誤的文件,造成危險,例如:php 檔案或其他腳本文件。CarrierWave 可以讓你指定允許的檔案類型存取。
白名單寫法,在名單中的才可以通過:

# avatar_uploader.rb

class AvatarUploader < CarrierWave::Uploader::Base
  def extension_whitelist
    %w(jpg jpeg gif png)
  end
end

黑名單寫法,在名單中的會被拒絕存入:
假設我們拒絕 JSON 的檔案

class NoJsonUploader < CarrierWave::Uploader::Base
  def content_type_blacklist
    ['application/text', 'application/json']
  end
end

參考資料:
GitHub - CarrierWave
PJCHENder未整理筆記

學無止盡,每天都要進步一點點!


上一篇
Day 26 - 上傳檔案 Carrierwave - 單一檔案
下一篇
Day 28 - 重要的鑰匙要藏好
系列文
關於 Ruby on Rails 的那些事30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言