来到第7篇了!培养写作习惯真是不容易:)
在我的上一篇文章活用套件carrierwave gem: (1)在Rails实现图片上传功能 ,上传图片功能已经完成啦!但是目前图片仅能上传在自己的本地资料夹内孤芳自赏。
如果我们要把网站完整的功能部署到正式环境,让其他网路使用者也可以一起上传图片,势必需要一个图片伺服器。目前最主流的Image Host之一算是AWS(Amazon Web Service)里的S3(Simple Storage Service)了。
在这边我们略过申请帐号的过程(需要绑信用卡号,但只要在一年内不超过特定用量就可免费。)
A. 安装Fog-AWS Gem与Figaro Gem
为了串接carrierwave上传到Amazon S3的功能,我们回到carrierwave gem在Github的页面Using Amazon S3这个段落好好研究。它要我们在Gemfile里新增gem “fog-aws”
,然后在carriewave/intializers
下,新增一个档名称叫做carrierwave.rb
,。
以它提供的範例程式上写的上来看:
CarrierWave.configure do |config| config.fog_provider = 'fog/aws' #required config.fog_credentials = { provider: 'AWS', #required aws_access_key_id: 'xxx', #required unless using use_iam_profile aws_secret_access_key: 'yyy', #required unless using use_iam_profile use_iam_profile: true, #optional, defaults to false region: 'eu-west-1', #optional, defaults to 'us-east-1' host: 's3.example.com', #optional, defaults to nil endpoint: 'https://s3.example.com:8080' #optional, defaults to nil } config.fog_directory = 'name_of_bucket' #required config.fog_public = false #optional, defaults to true
从研读程式码的过程中,我们很容易发现到了里面出现一个使用任何云端上传服务都会有的金钥及安全性的问题!如何避免之后程式码备份到Github上,Access Key被全世界的人看光光?
[解决方案]
这时候我们除了fog-aws,还要装一个gem叫做Figaro以解决上述问题。Figaro会帮我们修改Rail的configuration档,用环境变数ENV
代替金钥,并产生一个简单的YAML档。
YAML是一种写法优雅,适合表达、编辑资料结构与各种设定档的格式(注意:大小写和TAB键敏感!)。YAML近一步了解: Wiki|简书
现在我们马上来安装gem:
gem 'figaro'gem "fog-aws" #用双引号,因为里面有特殊字元"-"
然后在terminal跑bundle install
,
再重启伺服器rails s
(安装gem的三大步骤要牢记!)
这样我们一次就装好了figaro
和fog-aws
两支gem。
接着,按照Figaro主页README.md档的指示,到terminal输入bundle exec figaro install
:
tingdeMacBook-Air:yelpdemo tingtinghsu$ bundle exec figaro install create config/application.yml append .gitignore
这时候专案就会在config资料夹下产生了新的yml档:config/application.yml
。
之后git push
专案到git版控伺服器如github,figaro这支gem会用.gitignore
隐藏好application.yml
,帮助我们的私密资料无法被它人观看。
新手如我在修改程式码的时候,常常看到一些新名词,例如刚刚的fog-aws
,这时候去google一下定义,对于程式架构的理解是很有帮助的。我很好奇为何要用fog
(雾?️?)这个名词。ITHome的这篇文章有提到:原来fog(雾运算)是相对于cloud(云端运算)。
边缘运算是就近运算的概念,将运算更靠近资料源所在的本地区网(Local Network)内运算,尽可能不用将资料回传云端,以减少资料往返云端的等待时间及降低网路频宽成本。边缘运算通常是在本地端和云端两边交界的附近做运算处理,也就是资料进出区网附近的位置,这么做的目的,在于既可以将运算环境放在本地,同时又可以靠近云端边界附近,藉此跟云衔接。毕竟并不是全部的资料都能放在本地端运算,还是会有些需要更进一步分析及判断的资料,
B. 在Amazon S3建立新的bucket
Amazon S3的bucket(储存桶)是类似云端资料夹(~雾端资料夹?)的概念。新手推荐
初期接触Amazon S3服务的板友们,我很建议去这个lab按照教学操作,内容设计互动上还挺有趣的~
1. 进入Amazon S3 console,按下的create bucket
建立bucket。
输入Bucket Name和Region(区域)。注意(bucket是个物件,你的bucket name必须是个unique name和世界上其他人的bucket name都不一样)然指定一个区域(region),不同区域的bucket对于使用者的上传下载速率有显着影响。(原来如此!难怪后文出现了卡bug。)我选了我目前所在的城市Sydney。
在设定bucket的Permission页面时,一开始对于新手来说,将bucket设定为public是较爲容易的学习做法。(如果我们的资料是极为隐密的,就千万不能这样做!)
2. 在bucket内按upload上传一张图片(或任何档案),记下所在的host和region。
点开档案,可以看到每个档案都会有属于自己的独特网址。
s3-ap-southeast-2.amazonaws.com/tingsrailsdemo/Eiffel.jpg
从这行网址,就可以确认主机s3-ap-southeast-2.amazonaws.com
,区域是ap-southeast-2
,这两者是我们修改carrierwave.rb
所需要的参数。
host:"s3-ap-southeast-2.amazonaws.com", region: "ap-southeast-2"
3. 在Sercurity Credentials新增Access Key
在右上方点击我们的帐户,选单上会出现Sercurity Credential
(安全凭证)。按下之后,视窗会提醒你接下来的步骤要小心谨慎,按下Continue to Sercurity Credential
后出现以下画面:
点选 Create New Access Key
,然后Download Key File
可以下载新建好的Access Key。
C.到专案修改application.yml
我们用记事本打开热腾腾刚打好的钥匙Access Key!在刚刚figaro帮我们製作的application.yml
,放入金钥id和access key。
pusher_app_id: '放我的id'pusher_key: '放我的钥匙'pusher_secret: '放我的秘密路径'
我们使用的是Amazon S3,所以前面三个pusher修改为:
aws_access_key_id: '放我的刚刚建好的id'aws_secret_access_key: '放我刚刚建好的key'fog_directory: '我的Amazon S3 bucket名称'
以此类推,如果你使用Google Cloud,就要换成Google Cloud的变数和相对应的key。YAML对于任何多的空格space或tab都是敏感的,所以输入资料时要特别小心。
D.Config/initializers
新增新档carrierwave.rb
,代换参数,重启server。
在config/initializers/
路径下,新增carrierwave.rb
,将carrierwave提供给我们程式码贴过去修改,代换刚才提到figaro帮我们做好的ENV[]
环境变数:
CarrierWave.configure do |config| config.fog_provider = 'fog/aws' # required config.fog_credentials = { provider: 'AWS', # required aws_access_key_id: ENV["aws_access_key_id"], aws_secret_access_key: ENV["aws_secret_access_key"], host: "s3-ap-southeast-2.amazonaws.com", region: "ap-southeast-2" } config.fog_directory = ENV["fog_directory"] # required# optional, defaults to {}end
这边我们更动到了config
档案,记得要重启伺服器rails s
。
[Bug注意!]
host: "s3-ap-southeast-2.amazonaws.com", region: "ap-southeast-2"
这两行要代换成你所选择的Amazon aws伺服器主机区域,不然会产生问题!
后来我用关键字Excon::Errors::SocketError Broken pipe (Errno::EPIPE)
参考了这篇网誌终于搞定!
(跟Amazon S3相关功能的熟悉和随之而来的bug让我卡了两天)这篇文章的得来不易啊...。
C. 修改carriewave的uploader.rb
去app/uploaders/image_uploader.rb
,把storage :file
加上注解,消去storage :fog
的注解,让carriewave知道,现在我们要把图片要上传到Amazon S3去。
class ImageUploader < CarrierWave::Uploader::Base # Choose what kind of storage to use for this uploader: # storage :file storage :fog #Use Amazon S3 end def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end
=大功告成!=
试着用本机功能的上传按钮传图片,再点开图片网址确认。
这张照片已经放入Amazon S3的bucket啰!
我很开心地修改3家餐厅的资料,去Amazon S3的bucket确认,图片已经安安稳稳地躺在路径/upload/restaurant/image/餐厅id
里了。
下一篇要讲把上传Amazon S3的新功能Deploy部署到Heroku上!
我的Rails专案系列文章整理:
[Ting's笔记Day6] 活用套件carrierwave gem: (1)在Rails实现图片上传功能
[Ting's笔记Day5] 在部署到Heroku之前,将Rails专案从SQLite设定为PostgreSQL
[Ting's笔记Day4] 将Ruby on Rails专案部署到Heroku
Ref:
AWS活用术|善用容量无上限的S3储存服务
Amazon S3 简易储存服务介绍与教学(1/3)