ただ日々を記すもの

意識高めを装うことができます

【Scala, Play】S3に画像をアップロード

S3に画像をアップロードする方法を紹介していきます。

言語は、 Scala 、フレームワークは Playframework を使用しています。

1. S3にバケットを作成

まずは、S3への登録です。

1_1. バケットを作成

S3のトップ画面に表示される バケットを作成する を選択 f:id:RONKUN:20171227213247p:plain

  • バケット名
    任意のバケットの名前を入力
  • リージョン
    アジアパシフィック(東京)を選択
  • 既存のバケットから設定をコピー
    既存のものがなければ未選択

f:id:RONKUN:20171227213551p:plain

プロパティの設定が必要であればこちらで設定します。
私は特に設定しませんでした。 f:id:RONKUN:20171227213933p:plain

次はアクセス許可の設定です。
こちらもデフォルトのまま次へボタンを押下 f:id:RONKUN:20171227214100p:plain

最後に表示される確認画面で入力内容に問題がなければ
作成ボタンを押して完了です!

1_2. アクセスキーの設定

外部のアプリケーションから画像を登録する場合は、
アクセスキーの設定が必要になります。

画面右上の自身の名前をクリックし表示される セキュリティ認証情報 を選択。

ユーザーメニューを選択します。 f:id:RONKUN:20171227214708p:plain

ユーザーを追加 > 詳細を入力 > アクセス権限を設定 > 確認 > 完了! f:id:RONKUN:20171227214821p:plain

  • ユーザー名
    任意のユーザー名。今回はs3_uploadとしました。
  • アクセスの種類
    プログラムによるアクセス にチェックをつけます。
    ここにチェックをつけることで今回必要となる アクセスキー, シークレットアクセスキー が取得できます。

f:id:RONKUN:20171227214926p:plain

AmazonS3FullAccess を選択 f:id:RONKUN:20171227215314p:plain

設定を確認し、問題なければユーザー作成完了です。

これでS3にアクセスできるようになります。

2. 画像をアップロード

では、ここからはS3にアップロードする処理の紹介になります。

2_1. build.sbt

以下のライブライを読み込むようにします。

"com.amazonaws" % "aws-java-sdk" % "1.3.11"

2_2.html

下記は、scalaテンプレートを使用した書き方になります。

<form action="/upload" method="post" enctype="multipart/form-data">
    @CSRF.formField
    <div class="field">
        <label>写真</label>
        <input type="file" name="image">
    </div>
<button type="submit">画像を登録</button>
</form>

2_3.controller

  val bucketName     = "******" // 作成したバケット名
  val accessKey      = "******"  // アクセスキー名
  val secretKey      = "*******"  // シークレットアクセスキー名

  def upload() = Action(parse.multipartFormData) { implicit request =>
    request.body
      .file("image")
      .map { image =>
        import java.io.File
        val credential = new BasicAWSCredentials(accessKey, secretKey)
        val s3Client   = new AmazonS3Client(credential)

        val now      = DateTime.now()
        val fileName = image.filename

        val file = new File("/tmp", fileName)

        image.ref.moveTo(file) // localに保存
        val s3Path = s"images/${now.getYear}${now.getMonthOfYear}${now.getDayOfMonth}/$fileName"

        s3Client.putObject(
          new PutObjectRequest(
            bucketName, // 対象バケット
            s3Path, //S3保存パス
            file
          )
        )
        // Ok
      }
      .getOrElse {
        // Ng
      }

  }

以上です。

設定自体は非常に簡単にできました。 ただ、Fileオブジェクトを作成する際のpathのところがうまく行かず
色々試した結果今回の実装になっています。
ベターなやり方があればぜひ教えていただきたいです....