Ruby
Rails
S3
fog

fog-aws で S3 の pre-signed url を生成するときにオブジェクトの ACL と Cache-Control を設定する

あまりドキュメントが充実していないように思うので書きます.
コードは最低限のものしか載せていないので, ご自身の環境に合わせて読み替えたり追加したりしてください.

前提

Gemfile
gem 'fog'
gem 'fog-aws'

設定方法

put_object_url の引数の headersCache-Control を, optionsx-amz-acl を指定してあげれば OK です.
例:

.rb
time_to_access = 5.minutes

object_key = 'path/to/the/object'

headers = {
  'Cache-Control': 'max-age=3600',
}

options = {
  query: {
    'x-amz-acl': 'public-read',
  }
}

storage = Fog::Storage.new(
  provider: 'AWS',
  aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
  aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
  region: ENV['AWS_REGION'],
)

presigned_url = storage.put_object_url(
  ENV['AWS_BUCKET_NAME'],
  object_key,
  time_to_access.from_now.to_i,
  headers,
  options
)

注意点

生成した pre-signed url に向けてファイル等を送信するときは, headers で指定したものと同一のリクエストヘッダを設定しましょう.

また fog-aws はデフォルトで PUT メソッドを使ってデータを送信するものとして pre-signed url を生成するので, デフォルト設定に従っているのであれば POST ではなく PUT メソッドを利用しましょう (そうしないと AWS 側からは 403 Forbidden が返ってきてしまいます.)

例えば以下のような

.html
<input type='file' id='fileElem'>

<input> 要素を使ってユーザが選択したファイルをクライアントサイドから送信するコードは, (古の JS や $.ajax で記述すれば) 以下のようになるでしょう:

.js
var fileElem = document.getElementById('fileElem');

fileElem.addEventListener('change', function(e) {
  handleFiles(e.target.files);
}, false);

function handleFiles(files) {
  for(var i = 0; i < files.length; i++) {
    var file = files[i];

    $.get({
      // 何らかの方法で pre-signed url を返す action が controller 側で定義されているものとします
      url: 'presigned_url',
      dataType: 'json',
    })
    .then( function(response) {
      return $.ajax({
        url: response['presigned_url'],
        data: file,
        method: 'PUT',
        dataType: 'xml',
        headers: {
          'Cache-Control': 'max-age=3600',
        },
        processData: false,
        contentType: false,
      });
    })
    .done( function() {
      console.log('upload completed');
    });
  }
}

その他

headers では Cache-Control に限らず, x-amz-meta-xxx のようなユーザ定義メタデータも設定できます.

免責事項

本記事のコードを利用した結果, 不利益や損害が発生しても当方は責任を負いかねますので, ご自身の責任にてご利用ください.
特に AWS S3 はセキュリティ周りの設定が重要かと思いますので, 他の記事や公式ドキュメント等も合わせてご参照ください.
また本記事の内容について誤りがありましたら, ご指摘いただければ幸いです.