Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Rails 7でActiveStorage::Streamingサポートが追加(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

Rails 7でActiveStorage::Streamingサポートが追加(翻訳)

Active Storageが登場したことで、Railsのファイル保存が多くの点で改善されました。しかしファイルの「抽出方法」「ダウンロード方法」「ストリーミング方法」についてのサポートはわずかでした。

ダウンロードなどの基本的な機能についてはアプリで簡単にサポートできますが、より大きなファイルや動画ファイルはストリーミングにできると便利です。Netflixの時代はコンテンツを見るのに1分以上待ってくれる人などいません。配信はただちに行う必要があります。

これがストリーミングの利点です。ダウンロード方式ではファイルが最後までローカルコンピュータに読み込まれるまで待つことになりますが、ストリーミングならデータの一部(チャンク)だけを表示できるので、ユーザーの待ち時間が大幅に短縮されるのが便利です。Railsでストリーミングをサポートする方法を見てみましょう。

Active Storageからストリーミングするコントローラを独自に作りたい場合、ストリーミングを正しく行うメソッドがあると便利です。ストリーミングについてはActiveStorage::BaseControllerでもある程度のレベルまでサポートされていましたが、データが抽出されていないため使い勝手がよくありませんでした。

変更前

アップデート前のストリーミングで利用できるのは、いくつかの大まかな機能だけでした。

ブラウザがストリーミングファイルの表示機能をサポートしている場合は、以下のように書きます。

response.headers["Content-Type"] = @model.image.content_type
response.headers["Content-Disposition"] = "inline; #{@model.image.filename.parameters}"

@model.image.download do |chunk|
  response.stream.write(chunk)
end

この場合、ブラウザが表示すべきファイルの種類を認識するために、レスポンスヘッダーを手動で設定する必要がある点にご注目ください。ありがたいことに、今ならもっと良い方法があります。

変更後

コントローラでのファイルストリーミングをネイティブにサポートするメソッドが追加されました(#41440)。これによって導入されるActiveStorage::Streamingモジュールを任意のコントローラにincludeして#send_blob_streamメソッドを利用できるようになります。このメソッドには、クラウドストレージからblobをストリーミングするActionController::Base#send_streamがラップされています(changelog)。

コード例を見てみましょう。ここでは仮に「next Netflix」サービスを構築中だとしましょう。当然、動画のストリーミング機能が必要ですが、#send_blob_streamメソッドを用いて動画ファイルを渡すだけでできるようになります。このメソッドのパラメータでContent-Dispositionヘッダーも指定できます。指定なしの場合はContent-Dispositionが"inline"になります。

class VideoController < ApplicationController
  include ActiveStorage::SetBlob, ActiveStorage::Streaming

  def show
    http_cache_forever(public: true) do
      send_blob_stream @video, disposition: params[:disposition]
    end
  end
end

以上で完成です。これはRailsアプリケーションでストリーミングをネイティブにサポートする手軽な方法です。

関連記事

Railsの技: ナビゲーションリンクで便利なlink_to_unless_currentメソッド(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。