Ruby
AWS
S3

RubyからS3を利用する

やりたいこと

  • S3にHTMLの文字列をファイルとしてアップロードしたい
  • S3に存在するHTMLファイルをダウンロードしたい
  • ファイルにタグ付けしたい

やってみる

S3を扱う際、というかAWS-SDKにはResourceとClientが存在する
今回はResourceを利用する


環境

ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin17]
aws-sdk (3.0.1)


初期設定

アクセスキーやデフォルトリージョンの設定のためにAWS CLIをインストールして
aws configureを行っておく


Resource作成

require 'aws-sdk'
s3 = Aws::S3::Resource.new

bucket作成

# bucket_name = 'test_bucket20180808'
# _はバケット名に使用できない
bucket_name = 'test-bucket20180808'
bucket = s3.bucket(bucket_name)
# バケット名は全世界で一意でなければならないので存在した場合作成できない
bucket.exists? # => false
bucket.create
bucket.exists? # => true

オブジェクトのアップロード


テキストをオブジェクトとしてアップロードする場合

file_name = "#{Time.now.strftime("%Y%m%d")}.html"
s3_path = "site_a"
key = "#{s3_path}/#{file_name}"
obj = bucket.object(key)
# bodyには任意の文字列を渡せる
obj.put(body: 'hogehoge')
# 存在確認
obj.exists? # => true 
bucket.objects(prefix: 'site_a/').each{|obj| p key}
# => "site_a/20180808.html"

ファイルをアップロードする場合

file_name = "hoge_file"
s3_path = "site_b"
key = "#{s3_path}/#{file_name}"
obj = bucket.object(key)
obj.upload_file('log/test.log')  # => ホーム指定ができない?  
# 存在確認
obj.exists? # => true 
bucket.objects(prefix: "site").each {|obj| p obj.key}
"site_a/20180808.html"
"site_b/hoge_file"

オブジェクトのダウンロード


文字列として読み込む

key = "site_a/20180808.html"
obj = bucket.objects(key)
obj.get.body.read

 ファイルとして保存する場合

key = "site_a/20180808.html"
obj = bucket.objects(key)
file_name = "hogehoge"
obj.download_file(file_name)

基本的にはgetやputではなく
upload_file,download_fileを利用した方が良い

後者はサイズが大きい時に
自動的にマルチアップロード、ダウンロードを行ってくれるため


オブジェクトにタグ付け


tags = {env: "dev", name: "hoge"}.to_query
# to_queryはRails依存だったかも?
# URLエンコードする必要がある
key = "tagtest"
obj = bucket.object(key)
obj.put(body: 'hogehoge', tagging: tags)
# upload_fileの際も同じオプションでおk

タグ付けしたはいいものの、タグで指定してgetができませんでした
あったら教えてください


階層内で最新を取る

# s3://test-bucketxxxx/site_a/以下の最新のオブジェクトがほしい、そんな時
bucket.objects(prefix: "site_a").sort_by{|obj| obj.last_modified}.reverse[0]

あとがき

やろうとしてることがS3でやることではない気がします
最新や、更新対象にタグ付けして管理するつもりだったのですが・・・