LoginSignup
0
0

【Rails】carrierwaveでローカルに保存したファイルをアクションを経由して取得する

Last updated at Posted at 2024-01-29

はじめに

carrierwaveでpdfファイルを投稿し、そのファイルをクリックするとファイルを開く機能があります。
今回は、ファイルをローカル上のpublicディレクトリに保存しているためurl直打ちでファイル表示がされる対策のために、保存先をpublicディレクトリから変更し、ファイルのパスから直接取得するのではなくアクション経由で取得する方法に変更してurl直打ちで表示するのを防ぐ対応をしました。
carrierwaveでのファイルの投稿機能などについては今回のテーマの趣旨とは違うため省略します。

環境

ruby 3.1.2p20
Rails 7.0.4

テーブル

Posts
name
file

コントローラー

app/controllers/posts_controller.rb
def show_file
  file_path = Rails.root.join('uploads', 'post', 'file', params[:id], "#{params[:file_identifier]}.pdf") # ローカルに保存されているファイルのパス。保存先に合わせて変更する。

  if File.exist?(file_path) # ファイルがある場合
    send_data File.read(file_path), type: Mime::Type.lookup_by_extension(File.extname(file_path).delete('.')).to_s, disposition: 'inline' # send_dataでファイルを表示します。
  else # ない場合
    render plain: 'ファイルが見つかりません', status: 404
  end
end

ルーティング

config/routes.rb
resources :posts do
  member do
    get 'show_file/:file_identifier', to: 'posts#show_file', as: :show_file # urlに:file_identifierを含めることでposts#show_fileでファイル名を取得できるようにします。
  end
end

view

post.html.erb
# :file_identifierのパラメータに@post.file.identifierを渡すことでリンク先のposts#show_fileで:file_identifierを扱えるようにします。
<td><%= link_to @post.file, show_file_path(file_identifier: @post.file.identifier) %> </td>

最後に

これでリンクをクリックするとファイルが画面に表示されます。
アクションを経由して表示するため、ログインチェックやユーザーチェックなども実装できるようになりました。
本来はファイルはS3などにアップロードするのが一般的かもしれませんが、ローカルにファイルをおく場合はこのように実装していくのがいいのかなと思いました。
他にもっと良い実装方法はいくらでもあるとは思いますが、ひとまずこれで形にはなるかと思います。
この投稿に不手際や実装のアドバイスがありましたら、コメントいただけますと幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0