ruby on railsで AWS S3にファイルをアップロートといえば、carrywaveとかfogとか使ってファイルをアップロードしますね。
僕も普段はその方法を使っているのですが、それらってそもそもmodelにuploaderを生成したりとかしているんですね。
今回は、jsからカジュアルに画像をアップロードする仕組みを作りたかったので、サーバーサイドからファイルをアップロードしました。
その時の対応をメモしておきます。
Gemfileに以下を記述
gem 'aws-sdk', '~> 2'
bundle installすると以下がインストールされます
Installing aws-sdk-core 2.3.8 Installing aws-sdk-resources 2.3.8 Installing aws-sdk 2.3.8 (was 1.56.0)
クライアント
HTML
<div> <input type="file" name="img"/> </div> <a>送信</a>
Javascript
// formにデータをセット
var formData = new FormData();
if ($("input[name='img']").val() !== '') {
formData.append( "file", $("input[name='img']").prop("files")[0] );
}
$.ajax({
url: "/capture",
method: "PATCH",
dataType: "json",
data: formData,
processData: false,
contentType: false,
}).done(function( res ) {
if(res.result == true) {
// アップロード成功
} else {
// アップロード失敗
}
}).fail(function( xhr, status, error ) {
// アップロード失敗
});
サーバーサイド
Ruby on Railsですが、Controllerでリクエストを受け付けてから自作のライブラリーでawsにアップロードしています。処理が終わったらjsonで結果を返しています。この記事ではバリデーションやエラーハンドリングなどは無視しています。libで使用している’AWS_CONFIG’は、こちらで用意したconstantsです。設定情報は皆さんよしなにして下さい。
※ githubなどで公開されないようにして下さい。
Controller
ajaxで送られたデータは”ActionDispatch::Http::UploadedFile”オブジェクトとして扱われます。temfileでバイナリーを取得できます。
def capture
ImageLib.upload_capture_image(params[:file].tempfile)
render :json => { :result => true }
end
lib
# encoding: utf-8
class ImageLib
# 画像だけアップロードする
def self.upload_capture_image(file)
# Awsのconfigを設定
Aws.config[:credentials] = Aws::Credentials.new(AWS_CONFIG[:access_key_id], AWS_CONFIG[:secret_access_key])
Aws.config[:region] = 'ap-northeast-1'
# aws clientを生成
s3 = Aws::S3::Client.new
# アップロード
s3.put_object(
bucket: AWS_CONFIG[:bucket_name],
body: file,
key: "bucket内のアップロードするディレクトリ/ファイル名"
)
end
end
これでアップロードができます。あくまで記事に載せたのは簡略版なので、バリデーションやエラーハンドリングは自分で実装してね。
詳しくは公式の情報を閲覧下さい。
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/UploadObjSingleOpRuby.html
※ AWSの設定は.awsという名前で以下のように書くと読み込んでくれるようですが、私はうまく行きませんでした…
時間があるときに試してみたいと思います。
[default] aws_access_key_id = 'アクセスキー' aws_secret_access_key = 'シークレットキー'