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 支持 为额外的储存服务。⚠️还需要看帖子。
step by step 的网页,包括还未掌握的云存储,和服务器相关步骤:
https://afreshcup.com/home/2017/07/23/activestorage-samples
1.什么是ActiveStorage?
Active Storage上传文件到一个云存储服务如AmazonS3. 并且附加这件文件到Active Record objects。它基于本地磁盘服务,可以用于开发和测试以及支持镜像文件给次级服务用于备份和迁移。
使用Active Storage,一个程序可以转化文件通过ImageMagick上传。 以及生成文件代表无图像的文件,如PDF,或者video,以及提取元数据从任意文件。
2. Setup
ActiveStorage使用2个数据表储存文件。
运行rails active_storage:install 生成这2个数据表。
如果在本地开发,在config/environments/development.rb中,
config.active_storage.service = :local #默认已经设置了。
声明Active Storage 服务 在config/storage.yml中。 为了让你的程序使用云服务,需要提供一个名字和必须的配置。如amazon的配置:
本地和测试是默认的。
你需要告诉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.(不懂⚠️)
文件们从主服务被服务。
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直接创建:
调用avatar.attached?可以确定对象是否有了一个文件,返回true/false
3.2 has_many_attached macro宏命令
一对多的关系。一条记录可以附加多个文件。假如有一个message有多个images:
has_many_attached :images, dependent:false #记录删除但附加文件不会删除。
⚠️,如果使用has_many, 注意传的是一个数组,
更新:(7-1)
在views/_form.html.slim中,用form_for:
就会在web, products/new中显示一个上传框:choose files,⚠️是files, 这样就可以上传多个文件了。✌️
全代码:
备注: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
- 得到2018年的搜索记录。看第一条。
- 看相关的网页:
https://github.com/rails/rails/issues/31656 (还没有看。)
在product.rb中
validate :must_type
avatar.purge
# 使用in?(%w(image/png image/jepg))也可以。
avatar.purge
#if images.attached? 后面的代码大同小异,多images一个循环。
在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一起使用的 ,https://www.cnblogs.com/chentianwei/p/9227594.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) %>
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.例子:
8.2直接上传JavaScript events (这是一个涉及到JS前端的知识⚠️)
JS不熟悉,缺练习。
http://guides.rubyonrails.org/active_storage_overview.html#attaching-files-to-records
看动画演示:
按照顺序增加了7个JavaScript events事件。
- direct-upload:initalize
- direct-upload:start
- direct-upload:before-blob-request
- direct-upload:before-storage-request
- direct-upload:progress
- direct-upload:error
- 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上的内容。