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上的内容。 

相关文章
相关标签/搜索