Paperclip使用S3,並使用自訂的 Domain Name
先將paperclip預設的檔案路徑/system下的所有檔案直接搬到S3
- 建立bucket,記得bucket name
- 修改bucket policy,開放一般人的讀取權限
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowPublicRead", "Effect": "Allow", "Principal": "*", "Action": [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject" ], "Resource": [ "arn:aws:s3:::<bucket_name>/*", ] } ] }
- 在Web版介面直接上傳整個資料夾至bucket中(去掉原本的/system)
Rails裡修改設定
In application.rb
...
config.paperclip_defaults = {
storage: :s3,
s3_region: 'ap-northeast-1', // 以東京機房為例
s3_protocol: 'http', // http or https
s3_host_alias: <your_alias_host_name>, // 顯示給用戶的網址的host,會覆蓋下方的s3_host_name設定
s3_credentials: {
// 以下四項必填
bucket: <your_bucket_name>, // 剛剛創建的bucket名稱
access_key_id: <your_access_key_id>, // 此項與下一項是AWS給你的
secret_access_key: <your_secret_access_key>,
s3_host_name: 's3-ap-northeast-1.amazonaws.com' // 以東京機房為例
}
}
...
In attachment model
class Poi::Image < ResourceBlock
# 原本
has_attached_file :attachment, {
:styles => {
:thumb => "100x100#",
:small => "270x200#",
:medium => "500x375#"
},
:default_url => "/images/<model_name>/:style/"
}
# 後來
has_attached_file :attachment, {
:styles => {
:thumb => "100x100#",
:small => "270x200#",
:medium => "500x375#"
},
:url => ":s3_alias_url",
:s3_protocol => ..., // 此例中將會讀到'http'
:s3_host_alias => ..., // 此例中將會讀到<your_alias_host_name>
:path => "/:class/:attachment/:id_partition/:style/:filename"
}
end
Url解釋
在繼續說明問題前,先看我們碰到什麽問題
// S3上顯示的圖片的路徑是這樣
http://s3-ap-northeast-1.amazonaws.com/s3-ap.dingtaxi.com/product/images/attachments/000/001/031/small/Chiang_Mai_Old_City.jpg
// 應該是代表
https://:s3_host_name /:s3_bucket_name /:model_name /attachment /:id_partition/:style/image_file_name.jpg
// 但是可以發現,即使是換成下面這個也可以正確下載,顯示:s3_host_name/:s3_bucket_name == :s3_bucket_name.:s3_host_name 的事實
http://s3-ap.dingtaxi.com.s3-ap-northeast-1.amazonaws.com/product/images/attachments/000/001/031/small/Chiang_Mai_Old_City.jpg
// 雖然S3已經設定成接受跨站請求,但是在手機上時,全站是https,手機會擋下不是https的請求,所以要上https,上面的:s3_protocol在產品上要改成'https'
// 這造成另一個問題,因為S3實際上是沒有https的,所以瀏覽器會擋下未經驗證的https,警告使用者,又因為請求是圖片,所以警告不會跳出來...
// 所以才設定一個假名,即:your_alias_host_name,這裡設定的就是網站原本的host name
// 但該圖已經被搬到S3了,所以我們要再NginX設定foward proxy
NginX設定
http {
server_name <your_host_name>
server {
location ^~ /<model_name>/ {
proxy_pass http://s3-ap.dingtaxi.com.s3-ap-northeast-1.amazonaws.com/<model_name>/;
proxy_set_header X-Real-IP $remote_addr;
}
}
}