Skip to content

Instantly share code, notes, and snippets.

@syou007 syou007/Gemfile
Last active Oct 26, 2015

Embed
What would you like to do?
Railsで開発環境はpublicに書き込むS3にアクセスするクラスを書いた。 ref: http://qiita.com/syou007/items/44d92104c71f845d31fc
class AppConfig
# データを取得します。
def self.get(*keys)
yml = AppConfig.yml["app"]
keys.each { |key|
yml = yml[key.to_s]
}
return yml
end
private
# ymlデータを取得します。
def self.yml
# yamlファイルは毎回読む。
YAML.load_file("#{Rails.root}/config/app_config.yml")
end
end
app:
# S3関連
s3:
# 接続情報
access_key_id: 'access_key_id'
secret_access_key: 'secret_access_key'
region: 'ap-northeast-1'
# 環境ごとに変化する設定値
env:
development:
s3:
use: false
bucket: "bucket-develop"
production:
s3:
use: true
bucket: "bucket-production"
S3Accessor.put("file_path", "file_name", file_data)
S3Accessor.put("file_path", "file_name", params[:file].read)
S3Accessor.get("file_path/file_name")
S3Accessor.delete("file_path/file_name")
gem 'aws-sdk'
aws-sdk (2.1.24)
aws-sdk-resources (= 2.1.24)
aws-sdk-core (2.1.24)
jmespath (~> 1.0)
aws-sdk-resources (2.1.24)
aws-sdk-core (= 2.1.24)
# S3へのアクセッサー
# S3が全公開されている事が前提です。(HTTPアクセスを利用してます。)
class S3Accessor
require 'aws-sdk'
# S3のルートパスを返却します。
def self.root_url(root_url = "/")
if S3Accessor.s3_use?
# S3を使用している場合はS3のドメイン+バケット名を返却する。
return "https://s3-#{AppConfig.get(:s3, :region)}.amazonaws.com/#{S3Accessor.bucket}/"
else
# S3を使用しない場合はルートパスを返す。
return root_url
end
end
# S3に保存されているデータを取得します。
def self.get(path)
# 冒頭に"/"がある場合は削除する。
s3_path = path.index("/") == 0 ? path.sub("/", "") : path
# S3の使用可否で分岐
if S3Accessor.s3_use?
# S3を使用する場合(aws-sdkでアクセス出来るかもしれ無いが・・・)
# S3からデータを取得します。
file_data = nil
uri = URI.parse(S3Accessor.root_url + s3_path)
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') { |http|
# 送信
response = http.get(uri.request_uri)
# 取得したデータを保存します。
if response.code == "200"
# 返却用ファイルイメージを読み込みます。
file_data = response.body
else
raise "S3 Access Error! response code:#{response.code}"
end
}
return file_data
else
# 開発環境などでS3を使用しない場合
# ファイルを読み込みます。
file_data = nil
File::open("#{Rails.root}/public/#{s3_path}") {|f|
file_data = f.read
}
# 読み込んだファイルを返却する。
return file_data
end
end
# 指定のファイルをS3へアップします。
# 同名のキーがある場合は上書きします。
def self.put(path, filename, data)
# 冒頭に"/"がある場合は削除する。
s3_path = path.index("/") == 0 ? path.sub("/", "") : path
# 末尾に"/"がない場合は付与する。
s3_path << "/" unless s3_path.rindex("/") == s3_path.length
# S3の使用可否で分岐
if S3Accessor.s3_use?
# S3を使用する場合
# S3のインスタンスを取得
s3 = S3Accessor.s3_instance
# バケットを取得してファイルアップを行います。
obj = s3.bucket(S3Accessor.bucket).object("#{s3_path}#{filename}")
obj.put(body: data)
else
# 開発環境などでS3を使用しない場合
# ローカルに保存する場合はpublic配下に配置する。
local_path = "#{Rails.root}/public/#{s3_path}"
# ファイルパスがない場合は作成する。
FileUtils.mkdir_p(local_path) unless FileTest.exist?(local_path)
# ファイルを書き込みます。
File.open("#{local_path}#{filename}", 'wb') do|f|
f.write(data)
end
end
end
# S3のデータを削除します。
def self.delete(path)
# 冒頭に"/"がある場合は削除する。
s3_path = path.index("/") == 0 ? path.sub("/", "") : path
# S3の使用可否で分岐
if S3Accessor.s3_use?
# S3を使用する場合
# S3のインスタンスを取得
s3 = S3Accessor.s3_instance
# バケットを取得してファイルアップを行います。
obj = s3.bucket(S3Accessor.bucket).object(path)
obj.delete
else
# ローカルに保存する場合はpublic配下のファイルを削除する。
full_path = "#{Rails.root}/public/#{s3_path}"
# ファイルを削除する。
begin
File.delete full_path
rescue => e
Rails.logger.error("file delete error #{e}")
end
end
end
private
# S3のインスタンスを取得します。
def self.s3_instance
Aws::S3::Resource.new(access_key_id: AppConfig.get(:s3, :access_key_id),
secret_access_key: AppConfig.get(:s3, :secret_access_key),
region: AppConfig.get(:s3, :region))
end
# S3を使用するか?
def self.s3_use?
AppConfig.get(:env, Rails.env, :s3, :use)
end
# S3のバケット名を取得
def self.bucket
AppConfig.get(:env, Rails.env, :s3, :bucket)
end
end
<%= image_tag "#{S3Accessor.root_url(root_url)}file_path/file_name" %>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.