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アプリケーションでストリーミングをネイティブにサポートする手軽な方法です。
概要
原著者の許諾を得て翻訳・公開いたします。