Ruby on RailsでAWS S3から画像やファイルをダウンロード
AWSの画像をRailsで取得しブラウザでダウンロードする方法を書く。
主な設定は以下
- routesの編集
- 一時ダウンロードフォルダの作成
- photos_controller.rbの編集
- photos/index.html.slimの編集
routesの編集
routes.rbに以下を追加
1 2 3 4 5 |
resources :photos do member do get '/download_photo', to: "photos#download_photo" end end |
これで、「https://localhost:3000/photos/1/download_photo」というURLで画像をダウンロードできるようになる。
一時ダウンロードフォルダの作成
プロジェクトルート配下にimagetmpという名前のフォルダを作成
コマンドだと以下
1 |
mkdir imagetmp |
photos_controller.rbの編集
photos_controller.rbというコントローラの中に画像のダウンロードメソッドを作るとして、以下のメソッドを追加する。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
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 |
以下の=の後に値をセットし、ターミナルにコピペして環境変数をセット
1 2 3 4 |
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のダウンロードリンクを追加
1 |
= link_to "ダウンロード", download_photos_photo_path(photo.image_id), target: :_blank |
これでブラウザでダウンロードできるようになる。