[Ting's笔记Day7]活用套件carrierwave gem:(2)利用Amazon S3架设图片服务器

来到第7篇了!培养写作习惯真是不容易:)

在我的上一篇文章活用套件carrierwave gem:(1)在Rails实现图片上传功能,上传图片功能已经完成啦!但是目前图片仅能上传在自己的本地文件夹内孤芳自赏。/images/emoticon/emoticon25.gif

如果我们要把网站完整的功能部署到正式环境,让其他网络使用者也可以一起上传图片,势必需要一个图片服务器。目前最主流的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,。

以它提供的示例程序上写的上来看(leafor):

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,区域是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服务器主机区域,不然会产生问题(vmwork)!

后来我用关键字Excon::Errors::SocketError Broken pipe(Errno::EPIPE)参考了这篇网志终于搞定!

(跟Amazon S3相关功能的熟悉和随之而来的bug让我卡了两天/images/emoticon/emoticon14.gif)这篇文章的得来不易啊…。

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上!

上一篇:28. pt-table-sync


下一篇:Scala并发编程【快速入门】