原文:Ruby on Rails Guides — Active Storage Overview
轉貼自:https://calvertyang.github.io/2018/05/18/active-storage-overview/
Active Storage 是 Rails 5.2 所新增的功能,它可以讓你輕鬆的將檔案傳送到 Amazon S3、Google Cloud Storage 或 Microsoft Azure Storage 等雲端儲存服務,並將這些檔案附加到 Active Record。
支援一個主要雲端儲存服務,並在其它服務中建立鏡像以實現備援機制,它也提供了用於測試或本地部署的磁碟服務,但重點還是放在雲端儲存。
檔案可以從伺服器上傳到雲端或直接從客戶端上傳到雲端。
閱讀本指南後,你將知道:
- 如何附加一或多個檔案到記錄。
- 如何刪除檔案。
- 如何連結到檔案。
- 如何使用變體(variant)來轉換圖片。
- 如何產生非圖片檔案的預覽圖,如 PDF 或影片。
- 如何繞過應用程式伺服器,直接從瀏覽器上傳檔案到儲存服務。
- 如何清理測試過程中儲存的檔案。
- 如何實作對其它雲端儲存服務的支援。
1. 什麼是 Active Storage?
Active Storage 方便將檔案上傳到 Amazon S3、Google Cloud Storage 或 Microsoft Azure Storage 等雲端儲存服務,並將這些檔案附加到 Active Record 物件。它配備了本地磁碟服務以進行開發和測試,並支援將檔案鏡像到次要服務以進行備份和遷移。
使用 Active Storage,應用程式可以透過 ImageMagick 轉換上傳圖片,產生非圖片檔案(如 PDF 或影片)的預覽圖,並從任意檔案中提取中繼資料。
2. 安裝
Active Storage 在應用程式資料庫中使用兩個名為 active_storage_blobs
和 active_storage_attachments
的資料表。將應用程式升級到 Rails 5.2 後,執行 rails active_storage:install
來產生用來建立這些資料表的遷移。使用 rails db:migrate
來執行遷移。
在 config/storage.yml
定義 Active Storage 服務。對應用程式使用的每個服務,提供一個名稱和必要的設定。下面的範例定義了三個名為 local
、test
和 amazon
的服務:
|
|
透過設定 Rails.application.config.active_storage.service
告訴 Active Storage 要使用哪個服務。由於每個環境都可能使用不同的服務,因此建議在每個環境的基礎設定上進行。要在開發環境中使用先前範例中的磁碟服務,你可以將以下內容加到 config/environments/development.rb
:
|
|
要在生產環境使用 Amazon S3,你可以將以下內容加到 config/environments/production.rb
:
|
|
繼續閱讀來取得關於內建服務轉接器(如 Disk
和 S3
)及其所需設定的更多資訊。
2.1. 磁碟服務
在 config/storage.yml
定義磁碟服務:
|
|
2.2. Amazon S3 服務
在 config/storage.yml
定義 S3 服務:
|
|
將 aws-sdk-s3 gem 加到 Gemfile
:
|
|
Active Storage 的核心功能需要以下權限:
s3:ListBucket
、s3:PutObject
、s3:GetObject
和s3:DeleteObject
。如果你設定了其它上傳選項,如 ACL 設定,則可能需要額外的權限。
如果你想使用環境變數、標準 SDK 設定檔、設定檔、IAM 實例設定檔或工作角色,則可以省略上面範例中的
access_key_id
、secret_access_key
和region
值。Amazon S3 服務支援 AWS SDK 文件中描述的所有認證選項。
2.3. Microsoft Azure Storage 服務
在 config/storage.yml
定義 Azure Storage 服務:
|
|
將 azure-storage gem 加到 Gemfile
:
|
|
2.4. Google Cloud Storage 服務
在 config/storage.yml
定義 Google Cloud Storage 服務:
|
|
可以選擇提供一個 Hash 憑證來取代密鑰路徑:
|
|
將 google-cloud-storage gem 加到 Gemfile
:
|
|
2.5. 鏡像服務
你可以透過定義鏡像服務來讓多個服務保持同步。當檔案被上傳或刪除時,它會在所有鏡像服務中完成。鏡像服務可用來幫助生產環境中服務之間的遷移。你可以開始鏡像到新服務,將現有檔案從舊服務複製到新服務,然後全力投入新服務。根據上述定義你想要使用的每項服務,從鏡像服務中引用它們。
|
|
檔案由主服務提供。
3. 將檔案附加到記錄
3.1. has_one_attached
has_one_attached
指令設定了記錄和檔案間的一對一關係。每個記錄可以附加一個檔案。
例如,假設你的應用程式有一個 User
模型。如果想讓每個使用者都有一個頭像,請這樣定義 User
模型:
|
|
你可以建立一個帶有頭像的使用者:
|
|
呼叫 avatar.attach
將頭像附加到現有使用者:
|
|
呼叫 avatar.attached?
來確定特定使用者是否有頭像:
|
|
3.2. has_many_attached
has_many_attached
指令設定了記錄和檔案間的一對多關係。每個記錄可以附加多個檔案。
例如,假設你的應用程式有一個 Message
模型。如果想讓每個訊息都有多張圖片,請這樣定義 Message
模型:
|
|
你可以建立一則帶有多張圖片的訊息:
|
|
呼叫 images.attach
將圖片附加到現有訊息:
|
|
呼叫 images.attached?
來確定特定訊息是否有圖片:
|
|
譯者註:若使用 AJAX 來送出表單,可能會出現
No 'Access-Control-Allow-Origin' header is present on the requested resource.
的錯誤訊息,以 Amazon S3 為例,需要登入 AWS 後台修改 CORS 設定,設定範例如下:
|
|
4. 刪除檔案
要從模型中刪除附件,請在附件上呼叫 purge
。如果你的應用程式有設定使用 Active Job,刪除作業可以在背景完成。刪除作業會從儲存服務中刪除 blob 和檔案。
|
|
5. 檔案連結
為 blob 產生一個指向應用程式的永久連結。存取時,會返回一個重新導向到實際服務端點的連結。這種間接的方式將公開網址從實際網址分離開來,並允許例如鏡像不同服務中的附件以實現高可用性。重新導向連結的 HTTP 過期時間為 5 分鐘。
|
|
要建立下載連結,請使用 rails_blob_{path|url}
輔助方法。使用這個輔助方法可以讓你設定 disposition。
|
|
6. 轉換圖片
要建立不同尺寸的圖片,請在 Blob 上呼叫 variant
。你可以傳送任何 MiniMagick 所支援的轉換方式到此方法。
要啟用轉換功能,請將 mini_magick
gem 加到 Gemfile
:
|
|
當瀏覽器存取不同尺寸的圖片網址時,Active Storage 會將原始的 blob 延遲轉換為指定的格式,並導向到它新的服務位置。
|
|
7. 預覽檔案
一些非圖片檔案可以被預覽:也就是說,他們可以用圖片來呈現。例如,可以透過擷取第一個影格來預覽影片檔。Active Storage 內建支援預覽影片和 PDF 文件。
|
|
擷取預覽圖片需要第三方應用程式,用於影片的
ffmpeg
和用於 PDF 的mutool
。這些函式庫不是由 Rails 提供的。你必須自行安裝他們才能使用內建的預覽器。在安裝和使用第三方軟體前,請確定你了解這樣做所牽涉的許可。
8. 直接上傳
Active Storage 及其包含的 JavaScript 函式庫支援從客戶端直接上傳到雲端。
8.1. 安裝直接上傳功能
-
在應用程式的 JavaScript 封裝載入
activestorage.js
。
使用 Asset Pipeline:1
//= require activestorage
使用 npm 套件:
1 2
import * as ActiveStorage from "activestorage" ActiveStorage.start()
-
在檔案輸入欄位中註記直接上傳。
1
<%= form.file_field :attachments, multiple: true, direct_upload: true %>
-
就是這樣!在表單提交後會開始上傳檔案。
8.2. 直接上傳功能的 JavaScript 事件
事件名稱 | 事件目標 | 事件資料(event.detail ) |
描述 |
---|---|---|---|
direct-uploads:start |
<form> |
無 | 已提交包含直接上傳欄位的表單。 |
direct-upload:initialize |
<input> |
{id, file} |
表單提交後,處理每個檔案。 |
direct-upload:start |
<input> |
{id, file} |
開始直接上傳。 |
direct-upload:before-blob-request |
<input> |
{id, file, xhr} |
向你的應用程式請求直接上傳中繼資料之前。 |
direct-upload:before-storage-request |
<input> |
{id, file, xhr} |
請求儲存檔案之前。 |
direct-upload:progress |
<input> |
{id, file, progress} |
請求儲存檔案的進度。 |
direct-upload:error |
<input> |
{id, file, error} |
發生錯誤。除非此事件被取消,否則將顯示提醒 。 |
direct-upload:end |
<input> |
{id, file} |
直接上傳已結束。 |
direct-uploads:end |
<form> |
無 | 所有直接上傳都已結束。 |
8.3. 範例
你可以使用這些事件來顯示上傳的進度。
在表單內顯示上傳的檔案:
|
|
加上樣式:
|
|
9. 移除系統測試過程中儲存的檔案
系統測試透過復原(Rollback)交易來清理測試資料。因為 destroy 永遠不會在對像上呼叫,所以附加的檔案永遠不會被清理。如果你想清除檔案,可以在 after_teardown
callback 中完成。在此處操作可以確保測試過程中建立的連線都已完成,並且不會從 Active Storage 收到錯誤,表示無法找到檔案。
|
|
如果你的系統測試驗證是否刪除帶有附件的模型,並且使用 Active Job,請將測試環境設定為使用行內佇列轉接器,以便立即執行清除工作,而不是在未來的某個時間執行。
你可能也想為測試環境使用單獨的服務定義,以便你的測試不會刪除在開發過程中建立的檔案。
|
|
10. 實作支援其它雲端儲存服務
如果你需要支援除了這些以外的雲端服務,則需要實作 Service。每個服務都透過實作上傳和下載檔案到雲端所需的方法,來擴充 ActiveStorage::Service。
留言列表