XHack勉強会 第5回『Ruby「ゼロから」画像共有サービスを作る』で学んだこと
今回はAWSのS3というサービスに画像をアップロードし、
その画像をsnatraを使って表示させることを学びました。
その情報をまとめたので、ざっくりと説明します。
このノートでざっくり分かること。
【AWSの利用方法】
■AWSとは
アマゾンウェブサービスの略称であり、
あの有名なAmazonが提供してるサービス。
様々なITツール(サーバーやDB、アプリケーションなど)を
クラウド上で使用することが可能で、その種類も豊富。
今回は画像データをアップロードする為、
「S3」というストレージサービスを利用する。
■AWSアカウント後にやるべきこと
まずアカウントを作成したら、
[ルートアカウント認証情報を使用してサインイン]をクリック。
・ルートアカウントとは
AWSアカウントを作成したら、まずこのルートアカウントがもらえる。
これは全てのサービスを追加・使用する権限をもつアカウント。
パソコンで言うなら「管理者(権限を持ったユーザー)」と言ったり、
「Administrator(アドミニストレーター)」と言ったりする。
パソコンで別のユーザーを作って、そっちには権限を与えなければ
システムに影響を与えるソフトのインストールや設定ができなくなる。
そしてまず検索フォームで「IAM」と調べて、
そこでユーザーを追加する。
これで何をするかと言うと、
組織内でAWSアカウントを共有する場合、そのルートアカウントで
ログインさせてしまうと関係ないサービスを勝手に使われたり、
セキュリティ上好ましくない。
なので権限を設定し、特定のサービスやアクションのみしか
出来ないようにすることが出来る。
今回は「S3」を使うので、アクセス許可の設定では
「既存のポリシーを直接アタッチ」から検索フォームにて「S3」と検索。
リストから「AmazonS3FullAccess」をチェックして、ユーザー作成。
その時に表示されたページは、二度と表示されないので
必ずCSVダウンロードをして保管しておくこと。
これで準備はOK。
■S3の利用開始
先程作成したユーザーのURLにアクセスし、
「アカウント:」って書いてるところの数字は変えずにサインイン。
検索フォームに「S3」と入力し、S3にアクセス。
そして新しくバケットを作成。
・バケットとは
絵の通りバケツのこと。入れ物。
要はディレクトリみたいな感じと思えばOK。
「名前とリージョン項目」
・バケット名:好きなバケット名
・リージョン:「アジアパシフィック(東京)」
「アクセス許可の設定」
・パブリックアクセスを全てブロックのチェックを外す
(今回はsinatraからストレージ内画像データを参照するので)
を設定。
そして作ったバケット内にて試しに画像をアップロードする。
ファイルを追加後、
「アクセス許可を設定する」項目の「パブリックアクセス許可を管理する」を「アクセス権限を付与する」に変更。
アップロードしたファイルを見るには選択して「開く」。
そしてこの「オブジェクトURL」が外部からの接続先なのだが、
先程のアクセス権限を付与してなければこのURLに行っても見れない。
その時は「公開する」って押せばOK。
これで準備は完了。
【S3へ画像をアップロードして、ブラウザで表示する方法】
とりあえずまずファイル送信用の簡易的なフォームを作成を作成する為、
下記を「app.rb」に作成。
get '/test' do
return %Q{
<form action=upload method=post accept-charset=utf-8 enctype=multipart/form-data>
<div> # ファイル送信を行う時は必ずこれ↑を記入
<input type=file name=file value= id=file>
</div>
<div>
<input type=submit value="Upload ↑"> # [↑] とは上矢印(↑)の書き方
</div>
</form>
}
end
・%Q { }について
%記法の内の1つ。
%Q{ }で囲われた内側の””(ダブルクオート)を省略して書ける。
本当は<input type="file" name="file" value="" id="file">と書く。
(↑については特殊文字なので省略できない。)
そしてブラウザで確認するとこんな感じ。
次にS3と接続を行う為にGemファイルを使うのでインストール。
「Gemfile」に下記を追記してbundle install。
gem 'aws-sdk-s3' #sdkとは開発ツールのこと
そして「app.rb」に下記を追記。
require 'aws-sdk-s3'
get '/test' do
省略
end
# 下記を追記
post '/upload' do
upload_image = params[:file]
@file = upload_image["tempfile"] # アップロードするファイル
@type = upload_image["Content-Type"]
@key_name = "#{SecureRandom.hex}" # バケットに置く際のキー名(ランダムな英数字)
@s3 = Aws::S3::Resource.new(
region: 'ap-northeast-1', # リージョン東京
credentials: Aws::Credentials.new(
ENV['AWS_S3_ACCESS_KEY_ID'], # S3用アクセスキー
ENV['AWS_S3_SECRET_ACCESS_KEY'] # S3用シークレットアクセスキー
)
)
@s3.bucket(ENV['AWS_S3_BUCKET_NAME'])
.object(@key_name)
.put(body: @file, content_type: @type, acl: 'public-read')
# これでアップロード先のURLを取得できる
@image_url = @s3.bucket(get_bucket_name).object(@key_name).public_url
erb :image # 今回はimage.erbを使用
end
こちらも接続情報はdotenvを使うので、「.env」に下記を追記。
AWS_S3_ACCESS_KEY_ID='hogehoge'
AWS_S3_SECRET_ACCESS_KEY='hugahuga'
AWS_S3_BUCKET_NAME='foo'
そして表示部分の画面を作るが、今回は画像表示専用の画面を作成する。
名前を「image.erb」として下記を記載。
<img src= "<%= image["@image_url"] %>">
これでS3に画像をアップロードする準備ができたので、
ブラウザを起動し、[localhost:4567/test]に接続して
「ファイルを選択」ボタンを選択後、「Upload↑」ボタンでアップロード。
ブラウザに画像が表示されれば完了。
【DBに保存したURLでS3内の画像を表示する方法】
このままだとアップロードしたタイミングでしか見れないし、
他の画像も見るならまたアップロードしないといけない。
なのでアップロード先のURLをDBに保存、
そのURLを参照して画像を表示できるようにする。
・直接画像をDB内に保存しない理由
文字情報に比べると圧倒的にファイルサイズが大きく、動作が遅くなる為。
頻繁にやりとりをするDBでは、顕著にそれが現れるので
画像ファイル本体はDB外部に置き、場所だけDB内に保存して読み取る。
保存する為のDBテーブルを新規作成する為、
「create_image_contents.rb」を作成し下記を記載。
require "pg"
require "dotenv/load"
connect = PG::connect(
host: ENV['DATABASE_HOST'],
user: ENV['DATABASE_USER'],
password: ENV['DATABASE_PASSWORD'],
dbname: ENV['DATABASE_NAME'],
port: ENV['DATABASE_PORT']
)
@data = connect.exec("
CREATE TABLE image_contents (
id serial,
image_url text,
PRIMARY KEY (id)
);")
connect.finish
そして実行して下記のようにテーブルが出来たらOK。
そしてまずDBに取得したURLを保存する為に「app.rb」に下記を追記。
〜省略〜
@s3.bucket(ENV['AWS_S3_BUCKET_NAME'])
.object(@key_name)
.put(body: @file, content_type: @type, acl: 'public-read')
# 下記を追記
@image_url = @s3.bucket(ENV['AWS_S3_BUCKET_NAME']).object(@key_name).public_url
Mydatabase.exec("
INSERT INTO image_contents (image_url)
VALUES ('#{@image_url}');
")
redirect "/show"
end
get '/show' do
@data = Mydatabase.exec("select * from image_contents;")
erb :image
end
そしてDB内の画像を表示する為に「image.erb」を下記に書き直す。
<ul>
<% @data.each do |image| %>
<li>
<%= image["id"] %>
<br>
<img src= "<%= image["image_url"] %>">
</li>
<% end %>
</ul>
そして画像をアップロードして下記のように表示されれば完成。
ここまで来ると、もうほぼ完成間近。
これまでの知識を組み立てて作れるのが分かってきた。
基礎の中の基礎習得まであともう少し。
この記事が気に入ったらサポートをしてみませんか?