Ruby on RailsでAWS S3から画像をダウンロード

Ruby on RailsでAWS S3から画像をダウンロード

AWSの画像をRailsで取得しブラウザでダウンロードする方法を書く。
主な設定は以下

  • routesの編集
  • 一時ダウンロードフォルダの作成
  • photos_controller.rbの編集
  • photos/index.html.slimの編集

routesの編集

routes.rbに以下を追加

  resources :photos do
    member do
      get '/download_photo', to: "photos#download_photo"
    end
  end

これで、「https://localhost:3000/photos/1/download_photo」というURLで画像をダウンロードできるようになる。

一時ダウンロードフォルダの作成

プロジェクトルート配下にimagetmpという名前のフォルダを作成

コマンドだと以下

mkdir imagetmp

photos_controller.rbの編集

photos_controller.rbというコントローラの中に画像のダウンロードメソッドを作るとして、以下のメソッドを追加する。

require 'aws-sdk' # gem 'aws-sdk-rails'がGemfileに必要

def download_photo

  s3 = Aws::S3::Resource.new(
    access_key_id: ENV["AWS_ACCESS_KEY_ID"],
    secret_access_key: ENV["AWS_SECRET_KEY"],
    region: ENV["AWS_REGION"]
  )
  @photo = Photos.find(params[:id])
  extension = @photo.extension

  # 一旦サーバーに保存してからローカルにダウンロードさせる、access_key_id, secret_access_keyでアクセスさせたいため
  # ファイルの削除はherokuの場合自動でやらせる
  if !File.exist?("#{Rails.root}/imagetmp/#{@photo.image_id}.#{extension}")
    s3.bucket(ENV["AWS_BUCKET"]).object("store/#{@photo.image_id}").get(response_target: "#{Rails.root}/imagetmp/#{@photo.image_id}.#{extension}")
  end

  send_file "#{Rails.root}/imagetmp/#{@photo.image_id}.#{extension}", x_sendfile: true

end

以下の=の後に値をセットし、ターミナルにコピペして環境変数をセット

export AWS_REGION=
export AWS_ACCESS_KEY_ID=
export AWS_SECRET_KEY=
export AWS_BUCKET=

if !File.exist?のところは画像がサーバー内のimagetmp以下にダウンロードされてなかったら、S3から画像を取ってきてimagetmp以下に保存している。
これにより、すでにダウンロードされたものは2回目以降はS3からではなくサーバから取ってくるようにしている。
ダウンロード画像の種類が多いとimagetmp以下の画像数が肥大化してしまう可能性があるが、herokuの場合だと一定時間たったらgitで管理されてないファイルは自動で消されるので、その機能を用いて自動でやっている。

photos/index.html.slimの編集

htmlのダウンロードリンクを追加

= link_to "ダウンロード", download_photos_photo_path(photo.image_id), target: :_blank

これでブラウザでダウンロードできるようになる。

コメント