ActiveStorage Overview --Rails guide (history:7-1更新)

  • 如何attach一個或多個文件到一個記錄.has_many_attach()方法。
  • 如何刪除一個附加的文件。 purge方法
  • 如何鏈接到一個附加的文件。url_for()
  • 如何使用variants來轉化image。 ⚠️Variant/Variation模塊
  • 如何generate一個文件表明無圖像的文件,如PDF,或者video。⚠️忽略了。
  • 如何從瀏覽器發送一個文件上傳到一個存儲服務storage service, 經過你的應用服務 direct_upload: true方法,另外還增長了JavaScript event⚠️
  • 在測試期間如何clear儲存的文件⚠️我用的是參考書上的方法。
  • 如何implement 支持 爲額外的儲存服務。⚠️還須要看帖子。

 教程視頻:javascript

 

step by step 的網頁,包括還未掌握的雲存儲,和服務器相關步驟:css

https://afreshcup.com/home/2017/07/23/activestorage-samples 

 


 

1.什麼是ActiveStorage?html

 

Active Storage上傳文件到一個雲存儲服務如AmazonS3. 而且附加這件文件到Active Record objects。它基於本地磁盤服務,能夠用於開發和測試以及支持鏡像文件給次級服務用於備份和遷移。前端

使用Active Storage,一個程序能夠轉化文件經過ImageMagick上傳。 以及生成文件表明無圖像的文件,如PDF,或者video,以及提取元數據從任意文件。java

 


 2. Setup css3

 

ActiveStorage使用2個數據表儲存文件。git

運行rails active_storage:install  生成這2個數據表。github


若是在本地開發,在config/environments/development.rb中, web

config.active_storage.service = :local  #默認已經設置了。數據庫

 

 

聲明Active Storage 服務 在config/storage.yml中。 爲了讓你的程序使用雲服務,須要提供一個名字和必須的配置。如amazon的配置:

 本地和測試是默認的。

test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>
local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

 

amazon:
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  region: us-east-1
  bucket: your_own_bucket

 

你須要告訴Active Storage使用那個server。設定:

Rails.application.config.active_storage.service 

 

由於每一個環境使用的服務不同。因此推薦提早在環境中設置好。好比要在開發環境使用前面案例的disk 服務 , 你須要在config/environments/development.rb設置:

config.active_storage.service = :local     #默認已經設置了。

 

若是在production中,使用AmazonS3服務,配置config/environments/production.rb:

config.active_storage.service = :amazon

固然還要讀更多的信息關於內置服務適配器adapters(如Disk和S3)和它們須要的配置。 

 

2.1Disk Service

聲明 disk服務,在config/storage.yml中,默認已有了。

 

2.2 Amazon S3 Service

一樣須要在config/storage.yml中設置。

另外須要下載他的gem:gem 'aws-sdk-s3', require: false

(主流的雲服務都有gem)具體的都須要看相關文檔。

其餘Microsoft, Google(都須要下載gem) 

 

2.5 Mirror Service

經過定義一個鏡像服務,你能夠持有多個雲服務在異步下。

當一個文件上傳或刪除,它就經過了因此的鏡像服務。 

在產品環境中,鏡像服務之間可以經過一個遷移來使用。

你開業開始鏡像一個新的服務,拷貝現存的文件從舊服務到新服務,而後把全部的放在新服務上

Define each of the services you'd like to use as described above and reference them from a mirrored service.(不懂⚠️)

s3_west_coast:
  service: S3
  access_key_id: ""
  secret_access_key: ""
  region: ""
  bucket: ""
 
s3_east_coast:
  service: S3
  access_key_id: ""
  secret_access_key: ""
  region: ""
  bucket: ""
 
production:
  service: Mirror
  primary: s3_east_coast
  mirrors:
    - s3_west_coast

文件們從主服務被服務。

 


 

3 Attaching Files to Records

 

3.1 has_one_attached

能夠參考https://www.cnblogs.com/chentianwei/p/9169049.html 的寫法:

在建立一個對象時,不添加關聯。以後再使用:

@user.avatar.attach(params[:user][:avatar]) 來附加一個文件。

 

或者也能夠經過參數限制方法user_params直接建立:

def create
  user = User.create!(user_params)
  session[:user_id] = user.id
  redirect_to root_path
end
private
  def user_params
    params.require(:user).permit(:email_address, :password, :avatar)
  end

 

調用avatar.attached?能夠肯定對象是否有了一個文件,返回true/false 

 

3.2 has_many_attached macro宏命令

一對多的關係。一條記錄能夠附加多個文件。假若有一個message有多個images:

has_many_attached :images, dependent:false  #記錄刪除但附加文件不會刪除。

 

class MessagesController < ApplicationController
  def create
    message = Message.create!(message_params)
    redirect_to message
  end
 
  private
    def message_params
      params.require(:message).permit(:title, :content, images: [])
    end
end

 

⚠️,若是使用has_many, 注意傳的是一個數組,

 

更新:(7-1)

在views/_form.html.slim中,用form_for: 

  div.form-group
    = f.label :images
    = f.file_field :images,  multiple: true,  class:"form-control"

就會在web, products/new中顯示一個上傳框:choose files,⚠️是files, 這樣就能夠上傳多個文件了。✌️


全代碼:

h2 後臺,產品目錄
ul
  - @products.each do |product|
    li = link_to product.title, admin_product_path(product)
    - if product.avatar.attached?
        li = link_to image_tag(url_for(product.avatar), size: "100"), rails_blob_path(product.avatar, disposition:"attachment")
    - if product.images.attached?
      - product.images.each do |image|
        - if image.variable?
            li = link_to image_tag(image.variant(resize: "400x400")), rails_blob_path(image, disposition:"attachment")
            p = image.filename
        - elsif image.previewable?
            li = image_tag image.preview(resize: "200x200")
        - else
            li = image.filename

 

備註:product.avatar.variable? =>true; product.avatar.image? =>true;

圖片既是image也是variable. 

 

更新 7-2 

 

假設@post有一個image

file_field(:image, accept: 'image/png,image/gif,image/jpeg')

 :accept - If set to one or multiple mime-types, the user will be suggested a filter when choosing a file. You still need to set up model validations.

 

問題:如何設置validations。驗證上傳文件的格式。自定義?

 使用「how to validate uploaded file type in rails 5.2」進行google search

  1. 獲得2018年的搜索記錄。看第一條。
  2.  看相關的網頁:
https://stackoverflow.com/questions/48158770/activestorage-file-attachment-validation

https://github.com/rails/rails/issues/31656 (尚未看。)

 

在product.rb中

  validate :must_type 


  def must_type
    if avatar.attached?
      if avatar.blob.byte_size > 10
        errors[:base] <<  "#{avatar.blob.filename.to_s}太大,請選擇小於10mb的文件。"

avatar.purge

      elsif !avatar.blob.content_type.match (/^image\//)

# 使用in?(%w(image/png image/jepg))也能夠。

        errors[:base] << '非法文件格式,只支持圖片格式。'

        avatar.purge

      end
    end

    #if images.attached?  後面的代碼大同小異,多images一個循環。

  end

在views/../_form.html.slim中添加file_field的時候,須要添加accept特性

 = f.file_field :avatar, class:"form-control", accept: "image/jpg, image/jpeg, image/png, image/gif"

 

 


 

 

4 Removing Files 

purge: 把文件從storage中清除。

 

能夠從數據庫直接刪除:

ActiveStorage::Blob.find(🆔).purge 

ActiveStorage::Attachment.count   =>0

 

user.avatar.purge   #同步刪除avatar和實際的resource files。

user.avatar.purge_later   #異步刪除實際的resource files和關聯的models(經過Active job) 

異步清除ActiveStorage::Blob records 經過 ActiveStorage::Blob#purge_later方法  

使用Active job。在文件app/jobs/active_storage/purge_job.rb文件中:

def perform(blob) 

   blob.purge

end 

 

更新 7-1 

Activejob一個異步後端框架,能夠聲明jobs並讓它們在各類隊列後端運行
: 相關https://www.cnblogs.com/chentianwei/p/9123322.html

:和sidekiq一塊兒使用的 ,http://www.javashuo.com/article/p-ricwrfnj-mw.html

 


 

5. Linking to Files

 

建立一個顯示的url:

url_for(user.avatar) 能夠用在view中,如:image_tag(url_for(user.avatar), size: 200)

 

建立一個下載鏈接rails_blob_{path|url}  使用這個helper能夠設置配置,它可以指向active storage blob, 點擊連接就下載了。

例子: 

rails_blob_path(user.avatar, disposition: "attachment") 

<%= link_to image_tag(upload.preview(resize: "400x400")), rails_blob_path(upload, disposition: :attachment) %>

 


 

6 Transforming Images

Variants模塊須要使用gem 'mini_magick' ,同時必須安裝了imagemagick, 用brew安裝。

 

當瀏覽器擊中這個variant URL, Active Storage 將會轉化這個最初的blob爲你指定的格式。並重新定位到它的新服務位置。

variant(transformations)

<%= image_tag user.avatar.variant(resize: "100x100") %>

這會建立一個URL,以指定的格式給blob 

 

 image_tag(user.avatar)
# => <img src="/rails/active_storage/blobs/.../tiger.jpg" />
image_tag(user.avatar.variant(resize: "100x100"))
# => <img src="/rails/active_storage/variants/.../tiger.jpg" />
image_tag(user.avatar.variant(resize: "100x100"), size: '100')
# => <img width="100" height="100" src="/rails/active_storage/variants/.../tiger.jpg" />

 

✅已解決:個人圖片沒有正確生成! 

出現未知錯誤,多是因爲80template模版的問題。更新imagemagick便可。用brew upgrade.

 


 

7  Previewing Files預覽(videos, pdf)

一些非圖片的文件能夠被預覽,即以圖片的形式呈現。例如一個Video file能夠經過提取它的第一個frame來預覽。ActiveStorage 支持預覽視頻和PDF文件。

  

看API 

ActiveStorage::Preview < ObjectObject

一個video blob能夠經過提取它的第一個框架來預覽,一個pdf blob能夠經過提取它的首頁來預覽。

A previewer 提取一個preview圖像從一個blob中。

 

更新 7-1 

內置的previewers須要依賴第三方庫。這些庫不被Rails支持,須要本身安裝。

建立一個preview image of PDF須要使用一個叫mu tools的工具,

建立一個video須要使用ffmpeg。 

在你的terminal中運行: 

brew install mupdf-tools ffmpeg

而後在view中就能夠用了: 

<%= image_tag @slide_deck.presentation.preview(resize:"400x400")%> 

 

使用簡介:

1.源碼說明:

在  rails/activestorage/lib/active_storage/previewer/mupdf_previewer.rb

有2個值得解釋的方法:

一個是accept?,它確認須要的第三方插件mutool是否已經安裝,同時blob中的文件的格式是不是"application/PDF" 

一個是preview , 它處理實際工做。你下載原始文件,而後轉化出一個圖片,再而後加載它。

 

視頻教程: 


https://gorails.com/episodes/how-to-create-an-active-storage-previewer?autoplay=1 

 

按照視頻練習,由於 ❌使用80模版仍然出現❌提示。因此不能繼續下去了。而後改用普通的rails new app,安裝mini_magick和activestorage後仍然是相同的問題:

mini_magick:invalid 

複製問題最後一部分,谷歌一下,在stackoverflow上找到解決辦法:

更新brew upgrade imagemagick, 哈哈成功了,直接能夠預覽pdf了。

 

視頻講解如何預覽pptx即幻燈片,這不是能夠預覽的文件格式,須要自定義一個能夠接受這個格式的類,繼承自ActiveStorage::Previewer

Rails,內置三個格式的類的方法支持,MuPDF, PopplerPDF, Video 。其餘的文件格式須要本身設置,同時也須要第三方庫支持。本教程就是教學如何設置pptx預覽的。


 


 

 

8. Direct Uploads

Active Storage和他包含的JavaScript庫,支持直接從客戶端上傳到雲端。 

 

8.1 Direct upload installation

 

1. 包含 activestorage.js到你的程序的JavaScript bundle,

(已經默認添加了)在asset pipeline中使用app/javascripts/application.js:

//= require activestorage 

npm package:使用import * as ActiveStorage from ActiveStoragestart()

 

2. 所以就這一步,給上傳文件的視圖編輯位置,加一個選擇direct_upload: true.例子:

  <div class="field">
    <%= form.label :avatar %>
    <%= form.file_field :avatar, multiple:true, direct_upload: ture %>
  </div>

 

 


 

8.2直接上傳JavaScript events (這是一個涉及到JS前端的知識⚠️)

JS不熟悉,缺練習。 

http://guides.rubyonrails.org/active_storage_overview.html#attaching-files-to-records 

看動畫演示: 

按照順序增長了7個JavaScript events事件。 

 

  1. direct-upload:initalize
  2. direct-upload:start 
  3. direct-upload:before-blob-request
  4. direct-upload:before-storage-request
  5. direct-upload:progress
  6. direct-upload:error
  7. direct-upload:end

 

 

這裏涉及到前端的css動畫效果:

 

transition 讓你在必定的期間內,經過某個事件來依照設置逐步的的改變某個屬性的value。

https://www.w3schools.com/css/tryit.asp?filename=trycss3_transition_speed 

transition: 某個屬性,幾秒,形式。 如:默認是ease,能夠不寫,或寫其餘格式。

transition: width, 2s, ease 

 

transform: 包含2d和3d,能夠改變元素圖像的位置。移動,旋轉,傾斜。 


 

9⚠️不是很明白: Discarding Files Stored During System Tests

清除在系統測試時儲存的文件。見以前的博客:

https://www.cnblogs.com/chentianwei/p/9071330.html 

 

和rails guide操做不太同樣。

 

 


 

 

10 使用雲的話,須要用到這個類:Service

https://github.com/rails/rails/blob/master/activestorage/lib/active_storage/service.rb 

 

 若是你須要支持一個雲服務,你須要implement 這個服務。 每一個服務擴展了ActiveStorage::Service,經過執行這些上傳和下載文件的方法給雲。

⚠️:須要看ruby-china上的內容。 

相關文章
相關標籤/搜索