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 = 'シークレットキー'