LoginSignup
0
0

More than 5 years have passed since last update.

Railsでrange付きsend_fileを省メモリで行う方法 (実装中)

Last updated at Posted at 2019-03-11

概要

以下の要件を満たしたい。

  • rails
  • range付きでsend_fileしたい
  • 省メモリ

Railsのsend_fileはどう実装されているのか?

以下のように、rangeに対応していない。

メモ: to_pathにrespondさせることで、RackのSendFile middlewareのX-SendFileの処理にひっかかるようにしている。

メモ: send_dataの実装
https://github.com/rails/rails/blob/b13a5cb83ea00d6a3d71320fd276ca21049c2544/actionpack/lib/action_controller/metal/data_streaming.rb#L109

Railsのsend_fileをrangeに対応させた既存の実装

以下のような実装だが、ファイルをメモリ上に読み込むので、省メモリではない。

実際、俺はこの実装を使ってメモリ肥大化に苦しんだ。

Rackのsend_file(相当の機能)はどう実装されているのか?

以下のように、rangeに対応しつつ、少しずつ読み込んで返す実装らしい。

簡単な方法

rangeで切り出したファイルを別のファイルとして保存し、それをRailsのsend_fileで送信する。

ディスクも節約したい場合は使いづらい。
また、send_file直後に一時ファイルを削除するかんたんな方法もない(railsでafter response sent的なワードでぐぐってもそれらしいものが出てこない)。
Tempfileを使えばGC時に削除するのは可能。

-> Rack::TempfileReaperを発見 https://github.com/rack/rack/pull/671/files
これを使うと、send_file終了後にtempfileを削除できる

tempfile = Tempfile.new
request.env['rack.tempfiles'] << tempfile

とすれば良い

かっこいい方法

実装方針

TODO

参考1: https://gist.github.com/mudai/9415701

参考2:
include ActionController::Live
response.stream.write
response.stream.close

参考3: Rack::TempfileReaper

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