概要
aws-sdkでS3にアップしたPDFをCloudFrontから表示すると、ブラウザ上で表示されずにダウンロードされてしまいました。
結論
aws-sdkでS3にアップするときにContent-Typeに「application/pdf」を指定する必要があります。
設定しないと
Content-Typeが自動で「binary/octet-stream」と設定されるため、URLを開いてもブラウザ内で表示されずにダウンロードされます。
AWS マネジメントコンソールから変更しても反映されない
コンソール画面から手動で変更してもやはりダウンロードされてしまいます。(キャッシュの問題?よくわからない)
ちなみに、S3のオブジェクト詳細画面の右上の「開く」からはブラウザ内で表示されるようになります。
Blob形式でフロントに渡したらLINE内ブラウザでは開けない
aws-sdkを使って、S3のオブジェクトの実態をバイナリで取得し、Blob形式URLを作成して開く方式を最初は取っていました。主要なブラウザでは問題なく開けますが、LINE内ブラウザのようなWebViewでは開けないことが判明し断念しました。
Content-Dispositionを設定する
ブラウザ内で表示する方法としてContent-Dispositionをレスポンスヘッダにつける記事が出てきます。S3のメタデータにContent-Dispositionをinlineで設定しても何も変わりませんでした。
サンプルプログラム
ruby on railsで書いたサンプルコードです
def put(path, filename, data, bucket = BUCKET_NAME, overwrite: false, content_type: nil)
rv = true
# 冒頭に"/"がある場合は削除する。
s3_path = path.index("/")&.zero? ? path.sub("/", "") : path
# 末尾に"/"がない場合は末尾に"/"を付与する
s3_path += "/" if s3_path != "" && s3_path[-1] != "/"
# S3の使用可否で分岐
if S3Service.s3_use?
rv = false
begin
# S3のインスタンスを取得
s3 = S3Service.s3_instance
obj = s3.bucket(bucket).object("#{s3_path}#{filename}")
if overwrite || obj.exists? == false
# content_typeを指定してputする
rv = obj.put(body: data, content_type: content_type)
else
rv = true
end
rescue StandardError => e
Rails.logger.debug e
end
else
------(以下略)----------------------